A. Creating a Character
分析 : 注意有的情况c==0或c全部给b是可以的
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll min(ll a,ll b){return a<b?a:b;} ll max(ll a,ll b){return a>b?a:b;} int main() { int t; cin>>t; while(t--) { ll a,b,c; cin>>a>>b>>c; if(a+c<=b) { cout<<"0\n"; continue; } ll tmp=b+c-a; if(tmp<0) cout<<max(c+1,1)<<"\n"; else cout<<max(c-tmp/2,(ll)0)<<"\n"; } return 0; }B. Zmei Gorynich
分析 :略
code :
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 104; ll min(ll a,ll b){return a<b?a:b;} ll max(ll a,ll b){return a>b?a:b;} int main() { int t; scanf("%d",&t); while(t--) { int n,flag=0; ll u,v,x,maxv=0,p=0,ans=0; scanf("%d%I64d",&n,&x); for(int i=1;i<=n;i++) { scanf("%I64d%I64d",&u,&v); if(u>=x) flag=1; maxv=max(maxv,u-v); p=max(p,u); } if(flag) printf("1\n"); else if(maxv<=0) printf("-1\n"); else { ll num=(x-p)/maxv,ans=0; x-=num*maxv; ans+=num; if(x>p) ans+=2; else ans++; printf("%I64d\n",ans); } } return 0; }C. The Number Of Good Substrings
分析 : s[ l ] == 1 的区间最长取长度为18的,如果区间更长,则肯定大于 |s| , 但是需要加上有前导0的情况。
code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e5 + 3; int p[maxn]; int main() { int t; scanf("%d",&t); while(t--) { char s[maxn]; scanf("%s",s+1); int n=strlen(s+1),sum,ans=0; for(int i=1;i<=n;i++) if(s[i]=='0') p[i]=p[i-1]+1; else p[i]=p[i-1]; for(int len=1;len<=18;len++) for(int i=1;i<=n-len+1;i++) if(s[i]=='1') { sum=0; for(int j=0;j<len;j++) sum=(sum<<1)+s[i+j]-'0'; if(sum>=len&&i-(sum-len)-1>=0&&sum-len==p[i-1]-p[i-(sum-len)-1]) ans++; } printf("%d\n",ans); } return 0; }
D. Coloring Edges
分析 : 发现无环的时候k=1,有环的时候k=2,有环时可令E(u->v,u>v) 为一种颜色,E(u->v , u<v) 为另一种颜色,即可保证没有同色环。那么重点在于判断是否有环存在,按照拓扑排序遍历即可(见代码)
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5004; vector<int> p[maxn]; int deg[maxn],a[maxn],b[maxn]; bool top_sort(int n) { queue<int> q; int cnt=0; for(int i=1;i<=n;i++) if(!deg[i]) q.push(i); while(!q.empty()) { int x=q.front(),y; cnt++; q.pop(); for(int i=0;i<p[x].size();i++) { y=p[x][i]; deg[y]--; if(!deg[y]) q.push(y); } } return cnt==n; } int main() { int m,n; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&a[i],&b[i]); p[a[i]].push_back(b[i]); deg[b[i]]++; } if(top_sort(n)) { printf("1\n"); for(int i=1;i<=m;i++) printf("1 "); } else { printf("2\n"); for(int i=1;i<=m;i++) if(a[i]>b[i]) printf("1 "); else printf("2 "); } return 0; }
E. Sum Queries?
分析 :只需要两个某一位同时不为0的数即可,所以题目转化为求两个数满足某一位都不为0的和最小为多少,建立线段树维护每一位上不为0的数中最小值和次小值。这题代码实现对编程技巧要求较高(参考了某位神犇的博客),代码值得反复玩味
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 2e9 + 1; const int maxn = 2e5 + 3; int a[maxn]; struct SegmentTree { int l,r,minv[10],mn[10]; }t[maxn<<2]; void pushup(int p) { for(int i=0;i<10;i++) { t[p].minv[i]=min(t[p*2].minv[i],t[p*2+1].minv[i]); t[p].mn[i]=min(t[p*2].mn[i],t[p*2+1].mn[i]); t[p].mn[i]=min(t[p].mn[i],max(t[p*2].minv[i],t[p*2+1].minv[i])); } } void build(int p,int l,int r) { t[p].l=l,t[p].r=r; for(int i=0;i<10;i++) t[p].minv[i]=t[p].mn[i]=INF; if(l==r) { for(int x=a[l],now=0;x;x/=10,now++) if(x%10) t[p].minv[now]=a[l]; return; } int mid=(l+r)>>1; build(p*2,l,mid); build(p*2+1,mid+1,r); pushup(p); } void update(int p,int k,int x) { if(t[p].l==t[p].r) { for(int i=0;i<10;i++) t[p].minv[i]=t[p].mn[i]=INF; for(int y=x,now=0;y;y/=10,now++) if(y%10) t[p].minv[now]=x; return; } int mid=(t[p].l+t[p].r)>>1; if(mid>=k) update(p*2,k,x); else update(p*2+1,k,x); pushup(p); } pair<int,int> getmin(int p,int l,int r,int id) { if(t[p].l==l&&t[p].r==r) return make_pair(t[p].minv[id],t[p].mn[id]); int mid=(t[p].l+t[p].r)>>1; if(mid<l) return getmin(p*2+1,l,r,id); else if(mid>=r) return getmin(p*2,l,r,id); else { pair<int,int> a=getmin(p*2,l,mid,id),b=getmin(p*2+1,mid+1,r,id); return make_pair(min(a.first,b.first),min(min(a.second,b.second),max(a.first,b.first))); } } int main() { int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(q--) { int op; scanf("%d",&op); if(op==1) { int k,x; scanf("%d%d",&k,&x); update(1,k,x); } else { int l,r,ans=INF; pair<int,int> tmp; scanf("%d%d",&l,&r); for(int i=0;i<10;i++) { tmp=getmin(1,l,r,i); if(tmp.first!=INF&&tmp.second!=INF) ans=min(ans,tmp.first+tmp.second); } if(ans==INF) printf("-1\n"); else printf("%d\n",ans); } } return 0; }