Codeforces Round #442 (Div. 2) 题解(877A~F)
来源:互联网 发布:本地pubmed数据库 编辑:程序博客网 时间:2024/06/06 14:08
比赛传送门
前几天并没有打这场比赛,但是听说这场题目蛮水的(我的一位初三dalao朋友直接AK了),所以昨天打了打Virtual participation
先上题解:
A:
直接暴力枚举匹配即可,就是我写得麻烦了一点
#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>using namespace std;inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f;}char s[100010];int n;const char c[5][7]={' ','D','a','n','i','l',' ',' ','O','l','y','a',' ',' ',' ','S','l','a','v','a',' ',' ','A','n','n',' ',' ',' ',' ','N','i','k','i','t','a'};const int l[5]={5,4,5,3,6};inline bool check(int x){ bool flag; for(int i=0;i<5;i++){ flag=1;if(x+l[i]-1<=n){ for(int j=1;j<=l[i];j++)if(s[x+j-1]!=c[i][j])flag=0; if(flag)return 1; } } return 0;}int main(){ scanf("%s",s+1); int cnt=0;n=strlen(s+1); for(int i=1;i<=n;i++)if(check(i))cnt++; puts(cnt==1?"YES":"NO");}
B:
维护下a和b的前缀和,枚举两个交界点就可以了
代码比前一题好写到不知道哪里去了,但是很容易fst啊特别是交界点的特判(还好我打的是vp否则也跟着GG了
#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>using namespace std;inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f;}char a[100010];int s[100010],t[100010];int main(){ scanf("%s",a+1);int n=strlen(a+1); for(int i=1;i<=n;i++){ s[i]=s[i-1];t[i]=t[i-1]; if(a[i]=='a')s[i]++;else t[i]++; } int ans=0; for(int i=1;i<=n;i++) for(int j=i;j<=n+1;j++){ int p=s[i-1]+s[n]-s[j-1]+t[j-1]-t[i-1];//这里哪些要-1哪些不用就是fst的主要原因辣 ans=max(ans,p); } printf("%d",ans);}
C:
考虑到每个坦克只会移动到相邻两格,所以我们直接按照偶数格奇数格偶数格的顺序扫过去炸一下就好了(这样次数是最少的)
证明:显然成立(因为移动到相邻两格)
#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>using namespace std;inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f;}int main(){ int n=read(); printf("%d\n",n/2*2+(n-n/2)); for(int i=2;i<=n;i+=2)printf("%d ",i); for(int i=1;i<=n;i+=2)printf("%d ",i); for(int i=2;i<=n;i+=2)printf("%d ",i);}
D:
大力BFS,我们把每一个点记录一下走到的最少步数,然后向四个方向不断更新节点,但是要保证每个点只会进队一次,否则会MLE
时间复杂度
然后就过了23333???
后来看了一下官方题解做法很神奇(我看不懂),不过底下的讨论也给出了很多的不同BFS做法。。。亦可赛艇
#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>#define pa pair<int,int>#define mp make_pair#define fi first#define se secondusing namespace std;inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f;}const int dx[4]={1,-1,0,0};const int dy[4]={0,0,1,-1};int n,m,k,sx,sy,tx,ty;char s[1010][1010];int dist[1010][1010];bool vis[1010][1010];queue<pa>q;int main(){ memset(dist,-1,sizeof dist); n=read();m=read();k=read(); for(int i=1;i<=n;i++)scanf("%s",s[i]+1); sx=read();sy=read();q.push(mp(sx,sy));dist[sx][sy]=0;vis[sx][sy]=1; while(!q.empty()){ pa now=q.front();q.pop(); for(int i=0;i<4;i++){ int x=now.fi+dx[i],y=now.se+dy[i];int cnt=1; while(x>0&&x<=n&&y>0&&y<=m&&s[x][y]!='#'&&(dist[x][y]==-1||dist[x][y]==dist[now.fi][now.se]+1)&&cnt<=k){ dist[x][y]=dist[now.fi][now.se]+1; if(!vis[x][y])q.push(pa(x,y));vis[x][y]=1; cnt++;x+=dx[i];y+=dy[i]; } } } int tx=read(),ty=read(); printf("%d",dist[tx][ty]); return 0;}
E:
线段树维护dfs序区间修改裸题
打区间翻转(就是xor)的lazy标记就可以了
这种题显然是数据结构啊,看到这种子树的修改和询问操作想都不用想直接上就可以了
时间复杂度
#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>using namespace std;inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f;}int nedge=0,p[200010],nex[200010],head[200010];int n,t[800010],add[800010],lt[800010],rt[800010];int sx[200010],cnt=0,a[200010],s[200010],xs[200010];inline void addedge(int a,int b){ p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;}inline void dfs(int x){ sx[x]=++cnt;xs[cnt]=x;s[x]=1; for(int k=head[x];k;k=nex[k]){ dfs(p[k]);s[x]+=s[p[k]]; }}inline void pushdown(int nod){ if(!add[nod])return; if(lt[nod]!=rt[nod]){ add[nod*2]^=1;add[nod*2+1]^=1; t[nod*2]=rt[nod*2]-lt[nod*2]+1-t[nod*2]; t[nod*2+1]=rt[nod*2+1]-lt[nod*2+1]+1-t[nod*2+1]; }add[nod]=0;}inline void build(int l,int r,int nod){ lt[nod]=l;rt[nod]=r; if(l==r){t[nod]=a[xs[l]];return;} int mid=l+r>>1; build(l,mid,nod*2);build(mid+1,r,nod*2+1); t[nod]=t[nod*2]+t[nod*2+1];}inline void xg(int i,int j,int nod){ pushdown(nod); if(lt[nod]>=i&&rt[nod]<=j){ t[nod]=rt[nod]-lt[nod]+1-t[nod];add[nod]=1; return; } int mid=lt[nod]+rt[nod]>>1; if(i<=mid)xg(i,j,nod*2); if(j>mid)xg(i,j,nod*2+1); t[nod]=t[nod*2]+t[nod*2+1];}inline int ssum(int i,int j,int nod){ pushdown(nod); if(lt[nod]>=i&&rt[nod]<=j)return t[nod]; int mid=lt[nod]+rt[nod]>>1,ans=0; if(i<=mid)ans+=ssum(i,j,nod*2); if(j>mid)ans+=ssum(i,j,nod*2+1); return ans;}int main(){ n=read(); for(int i=2;i<=n;i++){ int x=read(); addedge(x,i); } dfs(1); for(int i=1;i<=n;i++)a[i]=read(); build(1,n,1); int m=read(); for(int i=1;i<=m;i++){ char c[5];scanf("%s",c);int x=read(); if(c[0]=='g')printf("%d\n",ssum(sx[x],sx[x]+s[x]-1,1)); else xg(sx[x],sx[x]+s[x]-1,1); } return 0;}
F:
最后一题有点意思,我并没有在两个小时的时间内写出来
%%%wzp(就是那位AKdalao)考场直接切掉了orz
这题是怎么被wzp想到莫队的啊QAQ
我们考虑对这整个数列做前缀和(种类和数量,具体看代码),记为
那么我们对于每个询问都这么暴力地去算,然后用莫队搞一下就好了
关键不在莫队,因为数值范围很大,所以我们需要对
时间复杂度貌似是
那就贴代码吧(WA了n发才过的QAQ)
#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>#define int long longusing namespace std;inline int read(){ int k=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();} return k*f;}struct ppap{int x,y,p,w;}qq[100010];inline bool cmp(ppap a,ppap b){return a.p==b.p?a.y<b.y:a.p<b.p;}int a[100010],s[100010],b[100010],q[100010],h[100010],now,n,k,ans[100010];inline void add1(int x){ if(h[x])now+=a[h[x]];a[s[x]]++;}inline void add2(int x){ if(q[x])now+=a[q[x]];a[s[x]]++;}inline void jian1(int x){ a[s[x]]--;if(h[x])now-=a[h[x]];}inline void jian2(int x){ a[s[x]]--;if(q[x])now-=a[q[x]];}signed main(){ n=read();k=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++){ int x=read(); s[i]=s[i-1]+((a[i]==1)?x:-x);//前缀和:第一种书+,第二种书- b[i]=s[i]; } sort(b+1,b+n+1);int cnt=unique(b+1,b+n+1)-b-1; int K=lower_bound(b+1,b+cnt+1,k)-b;if(b[K]!=k)K=0; for(int i=1;i<=n;i++){ q[i]=lower_bound(b+1,b+cnt+1,s[i]-k)-b;//记s[i]-k if(b[q[i]]!=s[i]-k)q[i]=0; h[i]=lower_bound(b+1,b+cnt+1,s[i]+k)-b;//记s[i]+k if(b[h[i]]!=s[i]+k)h[i]=0; } for(int i=1;i<=n;i++)s[i]=lower_bound(b+1,b+cnt+1,s[i])-b; h[0]=K;//以上全为离散化 int Q=read();int P=sqrt(n); for(int i=1;i<=Q;i++){ qq[i].x=read();qq[i].y=read(); qq[i].p=(qq[i].x-1)/P+1;qq[i].w=i; } sort(qq+1,qq+Q+1,cmp); memset(a,0,sizeof a); int l=1,r=0;now=0; for(int i=1;i<=Q;i++){ while(l<qq[i].x)jian1(l++); while(l>qq[i].x)add1(--l); while(r<qq[i].y)add2(++r); while(r>qq[i].y)jian2(r--); ans[qq[i].w]=now+a[h[l-1]];//因为是前缀和,有些以l为开头的合法区间要用l-1来算 } for(int i=1;i<=Q;i++)printf("%lld\n",ans[i]); return 0;}
总结:
这场题目算是比较水的了(至少对于前5题来说),题目也就简单的思路题和算法模板题了,F题比较有趣,考验思维和代码能力
(按照前5题的水平)关键是noip不会出这种大水题吧。。。 看来我还是得去做更难的题了
- Codeforces Round #442 (Div. 2) 题解(877A~F)
- Codeforces Round #442 (Div. 2) 877 F
- Codeforces Codeforces Round #452 (Div. 2)(899A-899F) 题解
- Codeforces Round #344 (Div. 2) A 题题解 (暴力)
- Codeforces Round #442 (Div. 2) 题解
- Codeforces Round #436 (Div. 2) (题解)
- Codeforces Beta Round #34 (Div. 2) A题解题报告
- Codeforces Round #179 (Div. 2) A题解题报告
- Codeforces Round #188 (Div. 2) A题解题报告
- Codeforces Round #185 (Div. 2) A题解题报告
- Codeforces Round #241 (Div. 2) A B C题解
- Codeforces Round #277 (Div. 2) A~E题解
- Codeforces Round #292 (Div. 2) A,B,C,D 题解
- Codeforces Round #303 (Div. 2) A,B,D题解
- Codeforces Round #304 (Div. 2) A,B,C题解
- Codeforces Round #311 (Div. 2) A~E && DE题解
- Codeforces Round #312 (Div. 2) A~E && CDE题解
- Codeforces Round #364 (Div. 2)(A,B,C,D) 题解
- 动画过渡效果
- 20171029 勇于挑战自己
- 1.netty基本概念
- C# lambda和Linq
- 从现在开始,每周坚持一个java知识点
- Codeforces Round #442 (Div. 2) 题解(877A~F)
- install kinnect senor on ubuntu
- [BZOJ2425][HAOI2010]计数(组合数学)
- ACM中国国家集训队论文集目录(1999-2009)
- Java中getResourceAsStream的用法
- JPEG 推荐的DC和AC系数的huffman(哈夫曼)码表
- 洛谷P1747 好奇怪的游戏(真的很奇怪哦~)
- 矩阵第二节
- 我的c语言自学之路