A题 水题 不解释
//By SiriusRen #include <bits/stdc++.h> using namespace std; int l,r,a; int main(){ scanf("%d%d%d",&l,&r,&a); if(l>r)swap(l,r); if(l+a<r)printf("%d\n",(l+a)*2); else{ a=a-(r-l),l=r; printf("%d\n",l*2+a/2*2); } }
B题 从左到右贪心 能选就选
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=100050; int n,m,tempa,tempb,ans,nb=1,a[N],b[N]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++)scanf("%d",&b[i]); for(int i=1;i<=n;i++){ tempa+=a[i]; while(tempb<tempa)tempb+=b[nb],nb++; if(tempa==tempb)tempa=tempb=0,ans++; } printf("%d\n",ans); }
C题
定义以0开始和结尾 中间01相间的串是"zebra"串
给你一个串 问它能不能分成k个子序列 使得这k个子序列都是"zebra"串
Special Judge
开两个set 分别存 0 1 出现的位置
贪心选取即可
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=200500; char s[N]; set<int>a,b; vector<int>vec[N]; set<int>::iterator ita,itb; int top,n; int main(){ scanf("%s",s+1),n=strlen(s+1); for(int i=1;i<=n;i++){ if(s[i]==‘0‘)a.insert(i); else b.insert(i); } while(!b.empty()){ if(a.empty()){puts("-1");return 0;} ita=a.begin(); vec[++top].push_back(*ita); while(1){ // printf("*ita=%d\n",*ita); itb=b.lower_bound(*ita); // printf("itb=%d\n",*itb); if(itb==b.end()){a.erase(ita);break;} // printf("!"); a.erase(ita); vec[top].push_back(*itb); ita=a.lower_bound(*itb); if(ita==a.end()){puts("-1");return 0;} vec[top].push_back(*ita); b.erase(itb); } } while(!a.empty()){ vec[++top].push_back(*(ita=a.begin())); // printf("%d\n",*ita); a.erase(ita); } printf("%d\n",top); for(int i=1;i<=top;i++){ printf("%d ",vec[i].size()); for(int j=0;j<vec[i].size();j++){ printf("%d ",vec[i][j]); }puts(""); } }
D题
找规律
n是奇数 -> 前n/2+1的数的位置不变 剩下的递归n/2并插空 循环右移一个位置
n是偶数 ->前n/2的数的位置不变 递归n/2
//By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long int solve(int x,int y){ if((y&1)&&x<=y&&(x&1))return x/2+1; else if(((y&1)==0)&&x<y&&(x&1))return x/2+1; else if((y&1)==1){ if(x==2)return solve(y/2,y/2)+y/2+1; else return solve(x/2-1,y/2)+y/2+1; } elsereturn solve(x/2,y/2)+y/2; } int n,q,x; signed main(){ scanf("%I64d%I64d",&n,&q); while(q--){ scanf("%I64d",&x); printf("%I64d\n",solve(x,n)); } }
E 连边tarjan 找入度为0的且点数最小的强连通分量
连边的要求 x=(y+1)%h x->y连边
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=200050; int n,m,h,u[N],xx,yy,v[N],nxt[N],first[N],tot,ans=0x3f3f3f3f; int low[N],dfn[N],cnt,vis[N],s[N],p[N],top,t,V[N],tempans,out[N]; void add(int x,int y){v[tot]=y,nxt[tot]=first[x],first[x]=tot++;} void tarjan(int x){ low[x]=dfn[x]=++cnt;vis[x]=1;s[++top]=x; for(int i=first[x];~i;i=nxt[i]) if(!dfn[v[i]])tarjan(v[i]),low[x]=min(low[x],low[v[i]]); else if(vis[v[i]])low[x]=min(low[x],dfn[v[i]]); if(low[x]==dfn[x]){t++;do xx=s[top--],vis[xx]=0,p[xx]=t,V[t]++;while(xx!=x);} } int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&m,&h); for(int i=1;i<=n;i++)scanf("%d",&u[i]); for(int i=1;i<=m;i++){ scanf("%d%d",&xx,&yy); if(u[xx]==(u[yy]+1)%h)add(yy,xx); if(u[yy]==(u[xx]+1)%h)add(xx,yy); } for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=n;i++) for(int j=first[i];~j;j=nxt[j]) if(p[i]!=p[v[j]])out[p[i]]=1; for(int i=1;i<=n;i++){ if(!out[p[i]]&&ans>V[p[i]])tempans=p[i],ans=V[p[i]]; }printf("%d\n",ans); for(int i=1;i<=n;i++)if(p[i]==tempans)printf("%d ",i); }
F
贪心
//By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long int n,d,b,a[100050],cntl,cntr; int sum(int l,int r){ if(l<1)l=1;if(r>n)r=n; return a[r]-a[l-1]; } signed main(){ scanf("%I64d%I64d%I64d",&n,&d,&b); for(int i=1;i<=n;i++)scanf("%I64d",&a[i]),a[i]+=a[i-1]; for(int i=1;i<=n/2;i++){ if(sum(1,i*(d+1))>=(cntl+1)*b)cntl++; if(sum(n-i+1-i*d,n)>=(cntr+1)*b)cntr++; }printf("%I64d\n",max(n/2-cntl,n/2-cntr)); }