Codeforces1099
A.Snowball
代码:
#include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; int w,h,u1,d1,u2,d2; int main(){ cin >> w >> h >> u1 >> d1 >> u2 >> d2; while(h){ w+=h; if(h==d1) w-=u1; if(h==d2) w-=u2; if(w<0) w=0; h--; } cout << w << endl; return 0; }
B.Squares and Segments
代码:(这题题意貌似有点问题,应该是要求满足面积大于等于N的最小花费)
#include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; int N,a,b; int main(){ cin >> N; a=b=1; for(int i=1;i<=N;i++){ if(a*b>=N) break; if(a<b) a++; else b++; } cout << a+b << endl; return 0; }
C.Postcard
代码:
#include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAXN=200+2; int N,c1,c2,K,p; char S[MAXN]; string T; int main(){ cin >> S >> K; for(int i=0;S[i];i++) if(S[i]>='a' && S[i]<='z') N++; else if(S[i]=='?') c1++; else c2++,p=i; if(N<=K){ if(!c2 && N!=K) cout << "Impossible"; else{ for(int i=0;S[i];i++){ if(S[i]>='a' && S[i]<='z') cout << S[i]; else if(S[i]=='?') continue; else if(i==p) for(int j=1;j<=K-N;j++) cout << S[i-1]; } } } else{ if(N-K>c1+c2) cout << "Impossible"; else{ for(int i=strlen(S)-1;i>=0;i--){ if(S[i]>='a' && S[i]<='z') T.push_back(S[i]); else if(N>K) i--,N--; } reverse(T.begin(),T.end()); cout << T; } } cout << endl; return 0; }
D.Sum in the tree
题意:给定一颗树中,深度为奇数的节点到根的点权和,求合法的整棵树的最小点权和。
题解:对于深度为偶数的节点,将其s设为所有儿子中最小的s;如果是叶子,就将其设为父节点的s。
代码:
#include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define ll long long const int MAXN=200000+2; struct HASH{ int u; HASH *next; HASH(){} HASH(int _u,HASH *_next):u(_u),next(_next){} }*tab[MAXN],mem[MAXN]; int N,cnt; ll s[MAXN],Ans; void Insert(int u,int v){ tab[u]=&(mem[cnt++]=HASH(v,tab[u]));} void DFS(int x,int f,int d){ ll b=INT_MAX; for(HASH *p=tab[x];p;p=p->next) DFS(p->u,x,d+1),b=min(b,s[p->u]); if(b==INT_MAX) b=s[f]; if(b<s[f]){ cout << -1 << endl; exit(0); } if(s[x]==-1) s[x]=b; for(HASH *p=tab[x];p;p=p->next) Ans+=s[p->u]-s[x]; } int main(){ cin >> N; for(int i=2,p;i<=N;i++){ cin >> p; Insert(p,i); } for(int i=1;i<=N;i++) scanf("%lld",s+i); /* for(int i=1;i<=N;i++){ cout << i << ":"; for(HASH *p=tab[i];p;p=p->next) cout << p->u << " "; cout << endl; } */ DFS(1,0,1); cout << s[1]+Ans << endl; return 0; }
E.Nice table
(待补)
F.Cookies
题意:给定一颗树,A每次可以向下移动一步;B每次可以切掉A所在节点与儿子的一条连边。A可以随时结束游戏,结束后往根走的同时,可以吃掉经过的节点的饼干,每吃一个饼干的时间与饼干所在节点有关,求在限定时间内,可以吃掉的最多的饼干。
题解:假定我们已经有了一条路径,显然吃饼干是从花费最小的开始吃,所以我们DFS,用线段树来记录路径上吃饼干的花费:用t作为角标,每个节点记录吃掉路径上[l,r]时间范围内的饼干的数量,和吃掉他们的花费。Query的过程可以参考代码。
代码:
#include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define ll long long const int MAXN=1000000+2; struct HASH{ ll u,w; HASH *next; HASH(){} HASH(ll _u,ll _w,HASH *_next):u(_u),w(_w),next(_next){} }*tab[MAXN],mem[MAXN]; int N,cnt; ll T,c[MAXN],t[MAXN],U; //Segment Tree begin struct NODE{ ll l,r; ll s,n; NODE(){} NODE(ll _l,ll _r):l(_l),r(_r),s(0),n(0){} }tree[6*MAXN]; void Pushup(int x){ tree[x].n=tree[2*x].n+tree[2*x+1].n; tree[x].s=tree[2*x].s+tree[2*x+1].s; } void Build(int x,ll l,ll r){ tree[x]=NODE(l,r); if(l==r) return; ll m=(l+r)>>1; Build(2*x,l,m),Build(2*x+1,m+1,r); } void Update(int x,ll p,ll v){ tree[x].n+=v,tree[x].s+=p*v; if(tree[x].l==tree[x].r) return; ll m=(tree[x].l+tree[x].r)>>1; if(p<=m) Update(2*x,p,v); else Update(2*x+1,p,v); } ll Query(int x,ll r){ if(tree[x].l==tree[x].r) return min(tree[x].n,r/tree[x].l); if(r<tree[2*x].s) return Query(2*x,r); else return tree[2*x].n+Query(2*x+1,r-tree[2*x].s); } //Segment Tree end void Insert(int u,int v,ll w){ tab[u]=&(mem[cnt++]=HASH(v,w,tab[u]));} ll DFS(int x,ll r){ if(r<=0) return 0; Update(1,t[x],c[x]); ll Ret=Query(1,r),a=0,b=0,rec; for(HASH *p=tab[x];p;p=p->next){ rec=DFS(p->u,r-2*p->w); if(rec>a) b=a,a=rec; else if(rec>b) b=rec; } Update(1,t[x],-c[x]); if(x==1) return max(Ret,a); else return max(Ret,b); } int main(){ cin >> N >> T; for(int i=1;i<=N;i++) scanf("%lld",c+i); for(int i=1;i<=N;i++) scanf("%lld",t+i),U=max(U,t[i]); for(int i=2,p,l;i<=N;i++){ scanf("%d %d",&p,&l); Insert(p,i,(ll)l); } cnt=0,Build(1,1,U); cout << DFS(1,T) << endl; return 0; }