A Rooms and Passages

题意

给n个数,从起点出发,一直往右走,遇到一个前面出现过其相反数的正数就停下,问对于每个起点都能走多少步。

分析

  • 倒着递推,如果起点是正数,那么肯定可以走,ans[i]=ans[i+1]+1
  • 如果起点是负数,那就得看这个负数对应绝对值在后面出现的最靠前的位置,而且还要看后面的负数所对应的绝对值的最靠前位置,所以这个lst应该是全局更新的。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=5e5+50;
int a[N],n,pos[N],ans[N];
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int lst=n+1;
for(int i=n;i>=1;i--){
if(a[i]>0){
ans[i]=ans[i+1]+1;
pos[a[i]]=i;
}else{
if(!pos[-a[i]]){
ans[i]=ans[i+1]+1;
}else{
lst=min(lst,pos[-a[i]]-1);
ans[i]=lst-i+1;
}
}
}
for(int i=1;i<=n;i++){
printf("%d%c",ans[i],i==n?'\n':' ');
}
return 0;
}

B Rearrange Columns

题意

有两行字符串,有#.,可以对列进行重排,使得#连在一起。

分析

  • 计算两个#,一个#在上面和在下面的,和没有#的,如果没有两个#而且#有上有下的,就不行。
  • 否则,把两个#的放中间即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+55;
char a[2][N];
int main(){
scanf("%s",a[0]);
scanf("%s",a[1]);
int n=strlen(a[0]);
int shang=0;
int xia=0;
int mei=0;
int liang=0;
for(int i=0;i<n;i++){
if(a[0][i]=='#' && a[1][i]=='#'){
liang++;
}else if(a[0][i]=='#' && a[1][i]=='.'){
shang++;
}else if(a[0][i]=='.' && a[1][i]=='#'){
xia++;
}else{
mei++;
}
}
if(liang || (shang &&!xia) || (xia&&!shang)){
printf("YES\n");
for(int i=0;i<mei;i++){
printf(".");
}
for(int i=0;i<shang+liang;i++){
printf("#");
}
for(int i=0;i<xia;i++){
printf(".");
}
printf("\n");
for(int i=0;i<mei;i++){
printf(".");
}
for(int i=0;i<shang;i++){
printf(".");
}
for(int i=0;i<liang+xia;i++){
printf("#");
}
printf("\n");
}else{
printf("NO\n");
}
return 0;
}

C Jumps on a Circle

题意

一个环标记为0到p-1,从0开始每次跳1,2,3...步,问跳n步之后会有多少个位置访问过。

分析

跳min(n,2p)次之后肯定会回到原点然后重新跳1,2,3...,所以模拟即可。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+50;
ll n,p;
int vis[N];
int main(){
scanf("%lld%lld",&p,&n);
vis[0]=1;
ll now=0;
for(ll i=1;i<=min(n,2*p);i++){
now=(now+i)%p;
vis[now]=1;
}
int ans=0;
for(ll i=0;i<p;i++){
ans+=vis[i];
}
printf("%d\n",ans);
return 0;
}

D Country Division

题意

给一棵树,每次询问给一些点染成红色,一些点染成蓝色,问能不能删掉一些边使得同色之间能相互到达,不同色之间不能相互到达。

分析

  • 因为是一棵树,如果可以删的话肯定删一条边就够了。
  • 假设1为根,先求红色点的lca,再求蓝色点的lca,如果两个lca不在同一棵子树,那么删掉其中一个连向父节点的边即可。
  • 如果两个lca有祖先关系,比如红色lca和蓝色lca的lca就是红色lca,那么如果红色点都在红色lca指向蓝色lca的另一条边上,那就可以,否则,说明有红色点在蓝色点的子树下。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
struct Edge{
int v,next;
}e[N*2];
int d[N],fa[N][20],pw[20];
int cnt,head[N];
void init(){
pw[0]=1;
for(int i=1;i<=20;i++){
pw[i]=pw[i-1]*2;
}
cnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v){
e[cnt]=Edge{v,head[u]};
head[u]=cnt++;
e[cnt]=Edge{u,head[v]};
head[v]=cnt++;
}
void dfs(int u){
for(int i=1;pw[i]<=d[u];i++){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==fa[u][0]){
continue;
}
fa[v][0]=u;
d[v]=d[u]+1;
dfs(v);
}
}
int lca(int x,int y){
if(d[x]<d[y]){
swap(x,y);
}
int tmp=d[x]-d[y];
for(int i=0;pw[i]<=tmp;i++){
if(tmp&pw[i]){
x=fa[x][i];
}
}
if(x==y){
return x;
}
for(int i=19;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int n,q,u,v,ri,bi,x,red[N],blue[N];
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
init();
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
dfs(1);
scanf("%d",&q);
while(q--){
scanf("%d%d",&ri,&bi);
scanf("%d",&red[1]);
int rlc=red[1];
for(int i=2;i<=ri;i++){
scanf("%d",&red[i]);
rlc=lca(rlc,red[i]);
}
scanf("%d",&blue[1]);
int blc=blue[1];
for(int i=2;i<=bi;i++){
scanf("%d",&blue[i]);
blc=lca(blc,blue[i]);
}
int lc=lca(rlc,blc);
if(rlc!=lc && blc!=lc){
printf("YES\n");
}else if(rlc==lc){
bool flag=false;
for(int i=1;i<=ri;i++){
if(lca(red[i],blc)==blc){
printf("NO\n");
flag=true;
break;
}
}
if(!flag){
printf("YES\n");
}
}else if(blc==lc){
bool flag=false;
for(int i=1;i<=bi;i++){
if(lca(blue[i],rlc)==rlc){
printf("NO\n");
flag=true;
break;
}
}
if(!flag){
printf("YES\n");
}
}
}
return 0;
}

E Third-Party Software - 2

题意

求最少的线段覆盖整个区间。

分析

贪心经典题。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
struct node{
int l,r,id;
bool operator <(const node& rhs)const{
if(l==rhs.l){
return r>rhs.r;
}else{
return l<rhs.l;
}
}
}a[N];
int n,m;
vector<int> res;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
}
sort(a+1,a+1+n);
int now=1,i=1,ans=0;
while(i<=n && now<=m){
int mx=0;
int k=0;
while(i<=n && a[i].l<=now){
if(a[i].r>mx){
mx=a[i].r;
k=i;
}
i++;
}
if(mx<=now-1){
ans=-1;
break;
}
res.push_back(a[k].id);
now=mx+1;
ans++;
}
if(now<=m){
ans=-1;
}
if(ans==-1){
printf("NO\n");
}else{
printf("YES\n");
printf("%d\n",ans);
for(int i=0;i<ans;i++){
printf("%d%c",res[i],i==ans-1?'\n':' ');
}
}
return 0;
}

F Friendly Fire

题意

n个怪兽,有两个属性a和b,如果属性a大于另一个怪兽的属性b,就可以打死该怪兽,现在要选出两个怪兽同时打,可能同时死,要使死的怪兽的属性a总和最大。

分析

  • 参考了entry上一个外国朋友的思路https://codeforces.com/blog/entry/67178
  • 考虑分别对a和对b递增排序,得到两个序列,然后枚举第一个序列的怪兽,然后把第二个序列中当前怪兽能打败的怪兽的a值加入优先队列中,因为这些怪兽肯定能被打死,所以直接取出最大的a值,然后再看取出的怪兽能否打败枚举的怪兽,再考虑是否再更新答案。
  • 如果取出的怪兽是本身,就取下一个,注意空队列的判断,取出的怪兽如果没用到,continue之前也要重新入队

代码

#include <bits/stdc++.h>
using namespace std;
const int N=3e5+50;
int n;
struct node{
int a,b,id;
}a[N],b[N];
bool cmp1(node a,node b){
if(a.a==b.a){
return a.b<b.b;
}else{
return a.a<b.a;
}
}
bool cmp2(node a,node b){
if(a.b==b.b){
return a.a<b.a;
}else{
return a.b<b.b;
}
}
priority_queue<pair<int,int> > q;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].a,&a[i].b);
a[i].id=i;
b[i]=a[i];
}
sort(a+1,a+1+n,cmp1);
sort(b+1,b+1+n,cmp2);
int ans=0;
int le=0,ri=0;
bool up=false;
for(int i=1,j=1;i<=n;i++){
while(j<=n && b[j].b<=a[i].a){
q.push({b[j].a,j});
j++;
}
if(q.empty()){
continue;
}
int mx=q.top().first;
int idx=q.top().second;
// printf("%d %d %d\n",i,a[i].a,a[i].b);
// printf("%d %d %d %d\n",idx,mx,b[idx].id,a[i].id);
if(b[idx].id==a[i].id){
// printf("%d F\n",i);
auto tmp=q.top();
q.pop();
if(q.empty()){
q.push(tmp);
continue;
}
mx=q.top().first;
idx=q.top().second;
q.push(tmp);
}
int t=mx+(b[idx].a>=a[i].b?a[i].a:0);
if(t>ans){
up=true;
ans=t;
le=a[i].id;
ri=b[idx].id;
}
}
printf("%d\n",ans);
if(!up){
printf("1 2\n");
}else{
printf("%d %d\n",le,ri);
}
return 0;
}

H Missing Number

题意

有0-n一共n+1个数,现在删去一个数,通过交互得到删去的数。

交互是询问第x个数的第i位是0还是1。

分析

  • 先分别询问每个数的最低位,统计1的个数,显然如果不缺数的话,1的个数应该是\(\frac{n+1}{2}\),可以由此判断缺的数这一位是0还是1。

  • 然后可以排除掉一半不符合的数,继续询问第2位。

  • 用set存数字下标(即第几个数)比较好写。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
set<int> ns,t;
int main(){
int n;
cin >> n;
for(int i=1;i<=n;i++){
ns.insert(i);
}
//从最低位开始询问
int i=0;
int res;
int ans=0;
while(ns.size()>=1){
int sz=ns.size();
t.clear();
int b=0;
for(auto it=ns.begin();it!=ns.end();it++){
int x=*it;
//询问第x个数的第i位
cout << "? " << x << " " << i << endl;
cout.flush();
cin >> res;
if(res){
t.insert(x);
b++;
}
}
if(b<(sz+1)/2){
//缺少的数第i位为1
ans+=(1<<i);
ns=t;
}else{
for(auto it=t.begin();it!=t.end();it++){
ns.erase(*it);
}
}
i++;
}
cout << "! " << ans << endl;
return 0;
}

I Painting a Square

题意

一个边长为b的小正方形给一个边长为a的大正方形涂色,问最小需要走的步数。

分析

  • 沿着边缘螺旋走进去是最优的。
  • 所以先沿这边缘走两个边长,就转化为a-b的小正方形的情况了。
  • 本地跑不出来所以手动栈模拟,不过评测机上能跑出来。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b;
ll fun(ll a,ll b){
// printf("%lld %lld\n",a,b);
if(a-b<b){
return 3ll*(a-b);
}else{
return fun(a-b,b)+2ll*(a-b)+b;
}
}
stack<ll>st;
ll solve(ll a,ll b){
ll aa=a;
while(aa-b>=b)
{
st.push(aa);
aa-=b;
}
ll ans=3ll*(aa-b);
while(!st.empty())
{
ans=ans+2ll*(st.top()-b)+b;
st.pop();
}
return ans;
}
int main(){
scanf("%lld%lld",&a,&b);
// ll ans=solve(a,b);
ll ans=fun(a,b);
printf("%lld\n",ans);
return 0;
}

J The Power of the Dark Side - 2

题意

n个人,每人有三种属性,如果有两种属性严格大于的话就能击败另一个人,问对于每个人,如果在每场战斗之前都能随意调整属性值,最多能击败多少人。

分析

  • 考虑每个人能被击败的条件,显然就是对方属性值总和至少有(两个最小的属性值+2)。
  • 所以把每个人能被击败的下限求出来,排序,然后枚举每个人的属性总和,upper_bound()查出能击败的人数,再判断这些人里面是否有自身。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+55;
ll a[N][3];
ll sum[N];
int n;
vector<ll> v;
vector<int> ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&a[i][0],&a[i][1],&a[i][2]);
sum[i]=a[i][0]+a[i][1]+a[i][2];
sort(a[i],a[i]+3);
v.push_back(a[i][0]+a[i][1]+2);
}
sort(v.begin(),v.end());
for(int i=1;i<=n;i++){
int k=upper_bound(v.begin(),v.end(),sum[i])-v.begin();
ll t=sum[i]-(a[i][0]+a[i][1]+2);
if(t>=0){
k--;
}
ans.push_back(k);
}
for(int i=0;i<n;i++){
printf("%d%c",ans[i],i==n-1?'\n':' ');
}
return 0;
}

K Deck Sorting

题意

分析后的题意是给一个只含RGB的字符串,从中抽出一个子序列,和剩下的子序列拼在一起,使得拼接后的字符串相同字符在一起。

分析

  • 枚举6个全排列,也就是拼接后的字符串情况,假设枚举RBG,那么就得把所有R取出。所有G剩下,要考虑的就是B,如果B是在最后一个R的后面,那就是跟随R取出,如果是在第一个G前面,那就跟随G留下,否则,即如果B在最后一个R前面且再第一个G后面,那就是不合法的。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+55;
char s[N];
set<char> lt;
char idx[]={'R','G','B'};
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++){
lt.insert(s[i]);
}
int siz=lt.size();
if(siz<3){
printf("YES\n");
}else{
for(int i=0;i<3;i++){
char le=idx[i];
for(int j=0;j<3;j++){
if(i==j){
continue;
}
char ri=idx[j];
char md=idx[3-i-j];
int leri=-1;
int rile=-1;
for(int k=n;k>=1;k--){
if(s[k]==le){
leri=k;
break;
}
}
for(int k=1;k<=n;k++){
if(s[k]==ri){
rile=k;
break;
}
}
bool flag=true;
for(int k=1;k<=n;k++){
if(s[k]==md){
if(k<leri && k>rile){
flag=false;
break;
}
}
}
if(flag){
printf("YES\n");
return 0;
}
}
}
printf("NO\n");
}
return 0;
}

M Shlakoblock is live!

题意

n个东西有p属性和v属性,现在可以选择将一些东西的v属性加1,求最大的每个东西的p的期望。

分析

p越大,v加1对期望的贡献肯定越大,所以对p排序,然后对v加1,更新答案,直到对答案没有影响就退出。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1050;
int t,n;
struct node{
ll zi,mu;
};
bool cmp(node a,node b){
return a.zi*b.mu>a.mu*b.zi;
}
struct info{
int p,v,id;
bool operator <(const info& rhs)const{
return p>rhs.p;
}
}a[N];
vector<int> ans;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d",&n);
ll zi=0,mu=0;
for(int i=1;i<=n;i++){
scanf("%lld%lld",&a[i].p,&a[i].v);
zi+=a[i].p*a[i].v;
mu+=a[i].v;
a[i].id=i;
}
sort(a+1,a+1+n);
ans.clear();
node tt{zi,mu};
for(int i=1;i<=n;i++){
zi+=a[i].p;
mu++;
node tmp={zi,mu};
if(cmp(tmp,tt)){
ans.push_back(a[i].id);
tt=tmp;
}else{
break;
}
}
ll g=__gcd(tt.zi,tt.mu);
printf("%lld/%lld\n",tt.zi/g,tt.mu/g);
int siz=ans.size();
sort(ans.begin(),ans.end());
printf("%d\n",siz);
if(!siz){
printf("\n");
}
for(int i=0;i<siz;i++){
printf("%d%c",ans[i],i==siz-1?'\n':' ');
}
}
return 0;
}

gym102215题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. CF1213G Path Queries

    题目链接 问题分析 直接按边从小到大加入,求所有的连通点对数量即可.最后离线询问.使用并查集维护Size. 参考程序 #include <bits/stdc++.h> using name ...

  2. NOI数论姿势瞎总结(Pi也没有)

    Miller-Rabin素数检测 费马小定理:没人不会吧. 二次探测:如果\(n\)是质数,\(x^2 \equiv 1\ (\mod n)\)的解只有\(x \equiv 1\)或\(x \equi ...

  3. 装win7英文版装系统学习

    1:语言变换,下载Vistalizator ,详细的方法点击:方法见.需要安装语言包,语言包地址请点击:语言包.

  4. java链接Mysql出现警告:Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by

    Java使用mysql-jdbc连接MySQL出现如下警告: Establishing SSL connection without server's identity verification is ...

  5. 胜利点20191010-5 alpha week 1/2 Scrum立会报告+燃尽图 03

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8747 一.小组情况组长:贺敬文组员:彭思雨 王志文 位军营 杨萍队名:胜 ...

  6. 八、MD5加密并封装,并调用封装方法

    一.MD5加密 封装Md5 public class Md5 { //十六进制下数字到字符的映射数组 private static final char hexDigits[] = { '0', '1 ...

  7. 浏览器端-W3School-HTML:HTML DOM Area 对象

    ylbtech-浏览器端-W3School-HTML:HTML DOM Area 对象 1.返回顶部 1. HTML DOM Area 对象 Area 对象 Area 对象代表图像映射的一个区域(图像 ...

  8. 阶段3 2.Spring_04.Spring的常用注解_2 常用IOC注解按照作用分类

    注解配置和xml的配置要实现的功能都是一样的.都是要降低程序间的耦合,只不过配置的形式不一样 打包方式改成jar 加入spring 的依赖 复制之前的代码过来 复制到我们新建的工程里 resurces ...

  9. fiddler抓取app的https的包

    线上问题的排查有时候需要抓包,但是是https协议的,则需要安装证书 在Android 6.0 (API level 23)及以前,APP默认信任系统自带的CA证书以及用于导入的CA证书,Androi ...

  10. Several ports (8005, 8080, 8009) required by Tomcat v8.5 Server at localhost are already in use.

    Several ports (8005, 8080, 8009) required by Tomcat v8.5 Server at localhost are already in use. The ...