首页 > 代码库 > 2014 ACM/ICPC Asia Regional Shanghai Online
2014 ACM/ICPC Asia Regional Shanghai Online
Tree http://acm.hdu.edu.cn/showproblem.php?pid=5044
树链剖分,区间更新的时候要用on的左++右--的标记方法,要手动扩展,用c++交,综合以上的条件可过。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #pragma comment(linker, "/STACK:36777216") 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 typedef __int64 LL; 8 const int M=100010; 9 struct G{ 10 struct E{ 11 int v,next; 12 }e[M<<1]; 13 int le,head[M]; 14 void init(){ 15 le=0; 16 mt(head,-1); 17 } 18 void add(int u,int v){ 19 e[le].v=v; 20 e[le].next=head[u]; 21 head[u]=le++; 22 } 23 }g; 24 int n,val[M],fa[M],dep[M],num[M],son[M],top[M],sid[M]; 25 void dfs(int u){ 26 num[u]=1; 27 son[u]=0; 28 for(int i=g.head[u];~i;i=g.e[i].next){ 29 int v=g.e[i].v; 30 if(v!=fa[u]){ 31 fa[v]=u; 32 dep[v]=dep[u]+1; 33 dfs(v); 34 if(num[son[u]]<num[v]) son[u]=v; 35 num[u]+=num[v]; 36 } 37 } 38 } 39 void get(int u,int Top){ 40 sid[u]=++n; 41 top[u]=Top; 42 if(son[u]) get(son[u],top[u]); 43 for(int i=g.head[u];~i;i=g.e[i].next){ 44 int v=g.e[i].v; 45 if(v!=fa[u]&&v!=son[u]){ 46 get(v,v); 47 } 48 } 49 } 50 LL lazy[M],ans[M]; 51 void query(){ 52 LL now=0; 53 for(int i=1;i<=n;i++){ 54 now+=lazy[i]; 55 ans[i]=now; 56 } 57 } 58 void update(int x,int y,int z){ 59 lazy[x]+=z; 60 lazy[y+1]-=z; 61 } 62 void worknode(int x,int y,int z){ 63 int tx=top[x],ty=top[y]; 64 while(tx!=ty){ 65 if(dep[tx]<dep[ty]){ 66 swap(tx,ty); 67 swap(x,y); 68 } 69 update(sid[tx],sid[x],z); 70 x=fa[tx]; 71 tx=top[x]; 72 } 73 if(dep[x]>dep[y]) swap(x,y); 74 update(sid[x],sid[y],z); 75 } 76 void workedge(int x,int y,int z){ 77 int tx=top[x],ty=top[y]; 78 while(tx!=ty){ 79 if(dep[tx]<dep[ty]){ 80 swap(tx,ty); 81 swap(x,y); 82 } 83 update(sid[tx],sid[x],z); 84 x=fa[tx]; 85 tx=top[x]; 86 } 87 if(x==y) return ; 88 if(dep[x]>dep[y]) swap(x,y); 89 update(sid[son[x]],sid[y],z); 90 } 91 struct IN{ 92 int type,u,v,w; 93 }in[M]; 94 struct EDGE{ 95 int u,v; 96 }edge[M]; 97 int main(){ 98 int t,N,m,u,v; 99 while(~scanf("%d",&t)){100 int cas=1;101 while(t--){102 scanf("%d%d",&N,&m);103 g.init();104 for(int i=0;i<N-1;i++){105 scanf("%d%d",&u,&v);106 g.add(u,v);107 g.add(v,u);108 edge[i].u=u;109 edge[i].v=v;110 }111 n=fa[1]=dep[1]=num[0]=0;112 dfs(1);113 get(1,1);114 char op[8];115 for(int i=0;i<m;i++){116 scanf("%s%d%d%d",op,&in[i].u,&in[i].v,&in[i].w);117 if(op[3]==‘1‘) in[i].type=1;118 else in[i].type=2;119 }120 mt(lazy,0);121 for(int i=0;i<m;i++){122 if(in[i].type&1) worknode(in[i].u,in[i].v,in[i].w);123 }124 printf("Case #%d:\n",cas++);125 query();126 for(int i=1;i<=N;i++){127 if(i>1) printf(" ");128 printf("%I64d",ans[sid[i]]);129 }130 puts("");131 mt(lazy,0);132 for(int i=0;i<m;i++){133 if(in[i].type==2) workedge(in[i].u,in[i].v,in[i].w);134 }135 query();136 for(int i=0;i<N-1;i++){137 int u=edge[i].u;138 int v=edge[i].v;139 if(dep[u]<dep[v]){140 swap(u,v);141 }142 if(i) printf(" ");143 printf("%I64d",ans[sid[u]]);144 }145 puts("");146 }147 }148 return 0;149 }
Contest http://acm.hdu.edu.cn/showproblem.php?pid=5045
根据题目要求,任意时刻都不能出现两个人做题数量的差大于1,也就是差要<=1,也就是m个问题要分成长度为n的等长的几块,每块里面一人做一个。
问题转化为n个人n题目,如何选一种排列来获得最大价值,若暴力枚举,复杂度是10!,所以用状态压缩,降为2^10,从000推到111.
转移时看哪个人没做过题,那么就可以让他做,状态就是他这位变为1,值就是当前状态的值加上这个人做当前的题目可获得的价值,当前的题目正好等于已做过题的人的个数+1.
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 double a[16][1024],dp[1<<10]; 7 int one(int x){ 8 int res=0; 9 while(x){10 if(x&1) res++;11 x>>=1;12 }13 return res;14 }15 int main(){16 int t,n,m;17 while(~scanf("%d",&t)){18 int cas=1;19 while(t--){20 scanf("%d%d",&n,&m);21 for(int i=0;i<n;i++){22 for(int j=0;j<m;j++){23 scanf("%lf",&a[i][j]);24 }25 }26 int s=0,num,all=1<<n;27 bool flag=true;28 double ans=0;29 while(flag){30 flag=false;31 if(s+n<m){32 flag=true;33 num=n;34 }35 else{36 num=m-s;37 }38 mt(dp,0);39 for(int i=0;i<all;i++){40 int yi=one(i);41 if(yi>=num) continue;42 for(int j=0;j<n;j++){43 if((i>>j)&1) continue;44 int next=i|(1<<j);45 dp[next]=max(dp[next],dp[i]+a[j][s+yi]);46 }47 }48 double big=0;49 if(num==n){50 big=dp[all-1];51 }52 else{53 for(int i=0;i<all;i++){54 if(one(i)==num){55 big=max(big,dp[i]);56 }57 }58 }59 ans+=big;60 s+=n;61 }62 printf("Case #%d: %.5f\n",cas++,ans);63 }64 }65 return 0;66 }
end
2014 ACM/ICPC Asia Regional Shanghai Online
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。