【HDU 5735】Born Slippy(状压dp)
2016-07-25 16:54
316 查看
【HDU 5735】Born Slippy(状压dp)
Total Submission(s): 833 Accepted Submission(s): 252
Problem Description
Professor Zhang has a rooted tree, whose vertices are conveniently labeled by 1,2,...,n. And the i-th vertex is assigned with weight wi.
For each s∈{1,2,...,n}, Professor Zhang wants find a sequence of vertices v1,v2,...,vm such that:
v1=s and vi is the ancestor of vi−1(1<i≤m).
the value f(s)=wv1+∑i=2mwvi opt wvi−1 is maximum. Operation x opt ydenotes bitwise AND, OR or XOR operation of two numbers.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n and a string opt (2≤n≤216,opt∈{AND,OR,XOR})– the number of vertices and the operation. The second line contains n integers w1,w2,...,wn (0≤wi<216). The thrid line contain n−1 integers f2,f3,...,fn (1≤fi<i), where fi is the father of vertex i.
There are about 300 test cases and the sum of n in all the test cases is no more than 106.
Output
For each test case, output an integer S=(∑i=1ni⋅f(i))mod(109+7).
Sample Input
3
5 AND
5 4 3 2 1
1 2 2 4
5 XOR
5 4 3 2 1
1 2 2 4
5 OR
5 4 3 2 1
1 2 2 4
Sample Output
91
139
195
Author
zimpha
Source
2016 Multi-University Training Contest 2
题目大意:
给出一棵树,每个点有点权。
定义f(s)=wv1+∑i=2mwvi opt wvi−1
s∈{1,2,...,n}
v为自选的集合。满足v1=s 并且 vi为vi−1的祖先2≤i≤m (m为选择的节点数量)
最直白的想法:dpi=maxj为i的祖先{dpj+(a+A)<<8+(b+B)}
a为dpj前八位 A为dpi前八位
b为dpj后八位 B为dpj后八位
这样是n2的复杂度,当然不可行
考虑优化,将遍历一个节点时,内部更新的O(n)降下来。
因wi为16位 考虑均拆为两部分 两个八位二进制。
这样考虑一个中间数组ds[x][y]表示之前所有祖先j中二进制前八位为x,当前位置wi二进制后八位为y时的最大值。(注意,这里暂不计入i和j前八位操作的结果)
这样在计算dp[i]时。
枚举祖先二进制前八位,因为确定当前节点i后,其实ds数组第二维(wi的后八位)就已知了。
然后取遍历过程中ds[x][y]+(wi前八位optx)<<8取最大值,即为dp[i]
这也是ds[x][y]不计前八位操作结果的原因。
这样通过dp[i]又可以更新ds[x][y] 其实此时i(以后遍历的节点的祖先)的前八位x又变成了已知的,枚举此时子孙可能的后八位,更新即可。
(不计后八位运算)
代码如下:
Born Slippy
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 833 Accepted Submission(s): 252
Problem Description
Professor Zhang has a rooted tree, whose vertices are conveniently labeled by 1,2,...,n. And the i-th vertex is assigned with weight wi.
For each s∈{1,2,...,n}, Professor Zhang wants find a sequence of vertices v1,v2,...,vm such that:
v1=s and vi is the ancestor of vi−1(1<i≤m).
the value f(s)=wv1+∑i=2mwvi opt wvi−1 is maximum. Operation x opt ydenotes bitwise AND, OR or XOR operation of two numbers.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n and a string opt (2≤n≤216,opt∈{AND,OR,XOR})– the number of vertices and the operation. The second line contains n integers w1,w2,...,wn (0≤wi<216). The thrid line contain n−1 integers f2,f3,...,fn (1≤fi<i), where fi is the father of vertex i.
There are about 300 test cases and the sum of n in all the test cases is no more than 106.
Output
For each test case, output an integer S=(∑i=1ni⋅f(i))mod(109+7).
Sample Input
3
5 AND
5 4 3 2 1
1 2 2 4
5 XOR
5 4 3 2 1
1 2 2 4
5 OR
5 4 3 2 1
1 2 2 4
Sample Output
91
139
195
Author
zimpha
Source
2016 Multi-University Training Contest 2
题目大意:
给出一棵树,每个点有点权。
定义f(s)=wv1+∑i=2mwvi opt wvi−1
s∈{1,2,...,n}
v为自选的集合。满足v1=s 并且 vi为vi−1的祖先2≤i≤m (m为选择的节点数量)
最直白的想法:dpi=maxj为i的祖先{dpj+(a+A)<<8+(b+B)}
a为dpj前八位 A为dpi前八位
b为dpj后八位 B为dpj后八位
这样是n2的复杂度,当然不可行
考虑优化,将遍历一个节点时,内部更新的O(n)降下来。
因wi为16位 考虑均拆为两部分 两个八位二进制。
这样考虑一个中间数组ds[x][y]表示之前所有祖先j中二进制前八位为x,当前位置wi二进制后八位为y时的最大值。(注意,这里暂不计入i和j前八位操作的结果)
这样在计算dp[i]时。
枚举祖先二进制前八位,因为确定当前节点i后,其实ds数组第二维(wi的后八位)就已知了。
然后取遍历过程中ds[x][y]+(wi前八位optx)<<8取最大值,即为dp[i]
这也是ds[x][y]不计前八位操作结果的原因。
这样通过dp[i]又可以更新ds[x][y] 其实此时i(以后遍历的节点的祖先)的前八位x又变成了已知的,枚举此时子孙可能的后八位,更新即可。
(不计后八位运算)
代码如下:
#include <iostream> #include <cmath> #include <vector> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <stack> #include <list> #include <algorithm> #include <map> #include <set> #define LL long long #define Pr pair<int,int> #define fread(ch) freopen(ch,"r",stdin) #define fwrite(ch) freopen(ch,"w",stdout) using namespace std; const int INF = 0x3f3f3f3f; const int msz = 1<<8; const int mod = 1e9+7; const double eps = 1e-8; struct Edge { int v,next; }; LL ds[256][256]; LL dp[66666]; bool vis[66666]; Edge eg[66666]; int head[66666]; int cf[66666][2]; LL val[66666]; LL mp[65537][256]; LL ans; int tp; void Add(int u,int v) { eg[tp].v = v; eg[tp].next = head[u]; head[u] = tp++; } void dfs(int u,int opt) { int a,b; a = cf[val[u]][0]; b = cf[val[u]][1]; dp[u] = 0; for(int i = 0; i < msz; ++i) { if(ds[i][b] == -1) continue; if(opt == 0) dp[u] = max(dp[u],1LL*(ds[i][b]+((i&a)<<8))); else if(opt == 1) dp[u] = max(dp[u],1LL*(ds[i][b]+((i|a)<<8))); else if(opt == 2) dp[u] = max(dp[u],1LL*(ds[i][b]+((i^a)<<8))); } ans = (ans+(1LL*dp[u]*u)%mod)%mod; //printf("dp[%d] %lld\n",u,dp[u]); int v; memcpy(mp[u],ds[a],sizeof(ds[a])); int k; for(int i = 0; i < msz; ++i) { if(opt == 0) k = i&b; else if(opt == 1) k = i|b; else if(opt == 2) k = i^b; if(ds[a][i] == -1) ds[a][i] = dp[u]+k; else ds[a][i] = max(1LL*ds[a][i],dp[u]+k); } for(int i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; // printf("%d-%d\n",u,v); dfs(v,opt); } memcpy(ds[a],mp[u],sizeof(mp[u])); } int main() { int a,b,tmp; a = 0; b = 0; while(a+b < 66666) { cf[a+b][0] = a>>8; cf[a+b][1] = b; // if(a+b >= 4350 && a+b <= 4360) // printf("%d %d %d\n",a+b,cf[a+b][0],cf[a+b][1]); b++; tmp = b>>8; tmp <<= 8; a += tmp; b -= tmp; } int t,u,n; scanf("%d",&t); char opt[5]; while(t--) { scanf("%d%s",&n,opt); ans = 0; for(int i = 1; i <= n; ++i) { scanf("%lld",&val[i]); ans = (ans+1LL*val[i]*i)%mod; } memset(head,-1,sizeof(head)); tp = 0; for(int i = 2; i <= n; ++i) { scanf("%d",&u); Add(u,i); } memset(ds,-1,sizeof(ds)); if(opt[0] == 'A') dfs(1,0); else if(opt[0] == 'O') dfs(1,1); else dfs(1,2); printf("%lld\n",ans); } return 0; }
相关文章推荐
- 代码提交的时候可以插入表情了-GitHub表情的使用
- freeMarker 遍历 list,map,list<map>
- Demo-jQuery下拉列表内容联动
- 从今天开始,做一个测试工程师
- 解决谷歌浏览器无法读取本地js文件
- Struts2与SpingMVC的开发对比
- 啥都不说了,就是这样搞!!!!
- js基础之DOM中元素对象的属性方法
- 跨域解决方案一:使用CORS实现跨域
- Tomcat 远程调试配置
- Unix环境高级编程笔记
- 关于 Android N 那些你不知道的事儿
- C#读写二进制文件
- 开发转测试? Yes or No
- linux--IT--top--笔记
- HDU 5750 Dertouzos
- $()的三种方法-jquery
- Demo-checkbox全(不)选,反选
- 使用表单标签 与用户交互
- Centos 6.5 压缩-解压方法