ZF_20160704_CF15X
来源:互联网 发布:泰安飞讯网络怎么样 编辑:程序博客网 时间:2024/06/05 20:30
246E
树上每个节点对应一个字符串,指定子树和深度,求不同字符串个数。
STL解决。
#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<set>#include<vector>#include<utility>#include<string>using namespace std;const int _=200010;int n,m;char c[_][33];namespace G{ int dep[_],dfn[_],lea[_],step; vector<int>V[_]; vector<pair<int,int> >Pt[_]; map<pair<int,int>,int>M; set<string>S; void dfs(int u,int f,int d) { dfn[u]=++step; Pt[d].push_back(make_pair(step,u)); dep[u]=d; int len=V[u].size(); for(int i=0;i<len;i++) { int v=V[u][i]; dfs(v,u,d+1); } lea[u]=++step; } int get(int v,int k) { if(M[make_pair(v,k)])return M[make_pair(v,k)]-1; S.clear(); vector<pair<int,int> >::iterator l=lower_bound(Pt[dep[v]+k].begin(),Pt[dep[v]+k].end(),make_pair(dfn[v],_)), r=lower_bound(Pt[dep[v]+k].begin(),Pt[dep[v]+k].end(),make_pair(lea[v],_)); for(vector<pair<int,int> >::iterator ir=l;ir!=r;ir++) S.insert(string(c[ir->second]+1)); return (M[make_pair(v,k)]=S.size()+1)-1; } int Go() { while(~scanf("%d",&n)) { for(int i=0;i<=n;i++)V[i].clear(),Pt[i].clear(); M.clear();S.clear(); for(int i=1;i<=n;i++) { int x; scanf("%s%d",c[i]+1,&x); V[x].push_back(i); } step=0; dfs(0,-1,1); scanf("%d",&m); while(m--) { int v,k; scanf("%d%d",&v,&k); printf("%d\n",get(v,k)); } } }}int main(){ G::Go();}
248D
一条街n个点,shop可买一块糖,给每个home送去一块糖,在时间限制t的前提下,求初始时带的糖的最小值。
对答案进行二分。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int dat[500010],n,m,num[500010],t,last,o;char c[500010];bool OK(int mid){ int tmp=1e9,res=0; num[0]=mid; m=last;//最后一个 home for(int i=1;i<=n;++i) { num[i]=num[i-1]+dat[i]; if(num[i]==0 && num[i-1]==-1)m=max(m,i); } if(m==0)return 1;//没有home for(int i=1;i<=m;++i) { res++; if(num[i-1]==0 && num[i]==-1) { o=i; tmp=min(tmp,res+(m-i)*2); } if(num[i-1]==-1 && num[i]==0) { res+=(i-o)*2; } } tmp=min(tmp,res); return tmp<=t;}int main(){ while(~scanf("%d%d%s",&n,&t,c+1)) { for(int i=1;i<=n;++i)dat[i]=c[i]=='H'?-1:c[i]=='S'?1:0; int l=0,r=0; for(int i=1;i<=n;++i) { if(dat[i]==-1)r++,last=i; if(dat[i]==1)l--; } l+=r; if(l<0)l=0;//shop 多 if(last>t){ puts("-1");continue; } while(l<r) { int mid=(l+r)/2; if(OK(mid)) r=mid; else l=mid+1; } printf("%d\n",r); }}
248E
f[u][i]u点有i个未用过的概率。
254E
f[i][j]第i天剩下j的食物。
0 0