/*A 題 題意:中文 解題:此題果斷二分,時間複雜度為 n*lgn ,注意最後的結果是 min ,理解其意 */#include<iostream> #include<cstdio> #include<string> #include<algorithm> #define manx 100009 using namespace std; long long a[manx]; int main(){ int n; while(scanf("%d",&n)!=EOF){ long long min=2000000009,max=0,sum=0; for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); if(min>a[i]) min=a[i]; if(max<a[i]) max=a[i]; } long long mid=(max+min)>>1,flag=0; while(max>min){ sum=0; flag=0; mid=(max+min)>>1; for(int i=1;i<=n;i++){ if(sum+mid<a[i]) { flag=1; break; } sum=sum+mid-a[i]; } if(flag){ min=mid+1; continue; } max=mid; } printf("%lld\n",min); } }
/*D 題 這道題想了我不知道多久了,一下午 + 一晚上 + 一上午,尼瑪啊,總算是找到規律了。。方法總結:找每個點的必敗點,也就是找最大的菱形,然後計算對點的步數。。 */#include<iostream>#include<cstdio>#include<algorithm> using namespace std;int main(){ int n,m ; while(cin>>n>>m){ if(n==m){ if(n%3==2)cout<<"Alice"<<endl; else cout<<"Bob"<<endl; continue; } int k=min(n,m); if(k%3==0) cout<<"Bob"<<endl; else cout<<"Alice"<<endl; }}
/*E題, 題意:中文 此題就是一道裸的KMP模板題 */#include<iostream> #include<cstdio> #include<string> #define manx 100009 using namespace std; char a[manx*2],b[manx]; int n,m,next[manx]; void get_next(){ //// 求next的值 int i=1,j=0; next[1]=0; //// 固定的值初始化 next[2]=1; while(i<m){ if(j==0||b[i]==b[i]){ ++i,++j; next[i]=j; ////這裡是遞推關係 } else j=next[j]; //// 注意了 這裡是重點 ,採用了記憶化 } } int kmp(){ int i=1,j=1; while(i<=n&&j<=m){ /// 匹配限制條件 if(j==0||a[i]==b[j]){ /// 匹配成立條件 ++i;++j; } else j=next[j]; /// 轉換,,思想真的要嚴老師講了才知道 } if(j>m) return i-m; return 0; } int main(){ while(cin>>a+1>>b+1){ n=strlen(a+1); m=strlen(b+1); if(!strcmp(a+1,b+1)){ printf("0\n"); continue;} int k=n; for(int i=n+1,j=1;i<=n+n && j<=n;i++,j++) a[i]=a[j]; n=n+n; get_next(); int flag=kmp(); if(!flag) printf("-1\n"); else printf("%d\n",k-flag+1); } }
/*C題,裸的線段樹,只是要維護幾個節點的值。。。 */#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define manx 100100 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 long long root[manx*4],x[manx],sum[manx*4],ans[manx*4],flag,val; void make(int l,int r,int rt){ if(l==r) { root[rt]=x[l]; sum[rt]=x[l]; ans[rt]=x[l]; return ; } int mid=(l+r)>>1; make(lson); make(rson); root[rt]=root[rt<<1] & root[(rt<<1)|1]; sum[rt]=sum[rt<<1] ^ sum[(rt<<1)|1]; ans[rt]=ans[rt<<1] | ans[(rt<<1)|1]; } void query(char s,int ll,int rr,int l,int r,int rt){ if(ll<=l && rr>=r){ if(!flag){ if(s=='a') val=root[rt]; if(s=='x') val=sum[rt]; if(s=='o') val=ans[rt]; flag=1; } else{ if(s=='a') val=val & root[rt]; if(s=='x') val=val ^ sum[rt]; if(s=='o') val=val | ans[rt]; } return ; } int mid = (l+r)>>1; if(rr<=mid) query(s,ll,rr,lson); else if(ll>mid) query(s,ll,rr,rson); else { query(s,ll,rr,lson); query(s,ll,rr,rson); } } int main(){ int n,m; while(cin>>n>>m){ for(int i=1;i<=n;i++) scanf("%lld",&x[i]); make(1,n,1); char s[4]; int l,r; for(int i=0;i<m;i++){ val=0; flag=0; scanf("%s %d %d",s,&l,&r); query(s[0],l,r,1,n,1); printf("%lld\n",val); } } }
/*F 題,建樹解題:先把每個元素看成一個單個集合,然後找出一個大集合作為主集合,每次找出一個大集合,然後進行合并 。。。 */#include<iostream>#include<algorithm>using namespace std;#define manx 20int x[manx],s[manx],pre[manx];int n,ans;int judge(){ ///判斷樹是否建成 for(int i=1;i<=n;i++) if(x[i]) return 1; return 0;}int query(){ /// 找出大集合 int max=0,ans; for(int i=1;i<=n;i++){ if(s[i]) continue; if(max<x[i]) max=x[i],ans=i; } return ans;}void fan(int pos){ /// 進行合并 for(int i=1;i<=n;i++){ if(s[i] && x[i]){ x[i]--; x[pos]--; s[pos]=1; pre[pos]=i; return ; } }}int main(){ while(cin>>n){ int max=0; for(int i=1;i<=n;i++){ s[i]=0; pre[i]=i; cin>>x[i]; if(x[i]>max) max=x[i],ans=i; } s[ans]=1; while(judge()){ int pos=query(); fan(pos); } for(int i=1;i<=n;i++){ if(pre[i]==i) continue; cout<<i<<" "<<pre[i]<<endl; } }}