HDU 5691
这B题目 一看就知道不会
看题解 听说是状态 压缩 立刻就不想写了 今天状态好点 写一下
dp[i][j] 代表 i 这个状态 第j个当做结尾插入的 最大的加起来的和
初始化也很神奇
先初始化没每个状态的1的个数 然后转移 列举前一个 这个
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> using namespace std; #define LL __int64 #define MAXN 10010 #define inf 1000000000 int cnt[(1<<16)+10]; int dp[(1<<16)+10][17]; int z[20],p[20]; int main() { int t,ca; scanf("%d",&t); for(int i=1;i<=(1<<16);i++) { int a=i; while(a>0) { if(a%2==1) cnt[i]++; a=a/2; } } ca=1; while(t--) { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d %d",&z[i],&p[i]); for(int i=0;i<(1<<n);i++) for(int j=0;j<=n;j++) dp[i][j]=-inf; z[n]=0; dp[0][n]=0; for(int i=0;i<(1<<n);i++) { for(int j=0;j<=n;j++) if(dp[i][j]!=-inf) for(int k=0;k<n;k++) { if(((1<<k)&i)==0&&(p[k]==-1||p[k]==cnt[i])) dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+z[j]*z[k]); } } int ans=-inf; for(int i=0;i<n;i++) ans = max(ans,dp[(1<<n)-1][i]); printf("Case #%d: %d ",ca++,ans); } return 0; }
HDU 5692
唯一的缺点就是没看到这是一棵树 0 开始到某个要去的点 显然不可能回来 哈哈哈 最多就只能走下去
感觉做过类似的 dfs 把每个点走一下标上号 然后 算出每个点到 父亲的距离 然后 转化到线段树上
怎么建树呢 1-n 带表 dfs序列 查询这个点就是 查询这个点 包括的子树的 l r 然后这个在dfs的时候就 处理出来了
然后 更新呢 就是 lazy 子树都要更新
更新的权值呢 y-w[b] w[b]=y 真厉害 long long 哈哈哈
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> using namespace std; #define ll __int64 #define MAXN 100010 #define inf 1000000000000 int head[MAXN]; struct edg { int to,next; }edge[MAXN*2]; int cnt,num; ll w[MAXN],dis[MAXN],ls[MAXN],rs[MAXN],ind[MAXN]; void add(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } struct node { int l,r; ll w,lz; }tree[MAXN<<2]; void dfs(int u,int fa) { num++; ls[u]=num; ind[num]=u; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==fa) continue; dis[v]=dis[u]+w[v]; dfs(v,u); } rs[u]=num; } void Push_down(int a) { tree[a<<1].lz+=tree[a].lz; tree[a<<1].w+=tree[a].lz; tree[a<<1|1].lz+=tree[a].lz; tree[a<<1|1].w+=tree[a].lz; tree[a].lz=0; } void Push_up(int a) { tree[a].w=max(tree[a<<1].w,tree[a<<1|1].w); } void Build(int l,int r,int a) { tree[a].l=l; tree[a].r=r; tree[a].lz=0; if(l==r) { tree[a].w=dis[ind[l]]; return ; } int mid=(l+r)>>1; Build(l,mid,a<<1); Build(mid+1,r,a<<1|1); Push_up(a); } void Update(int l,int r,int l1,int r1,ll w1,int a) { if(l1<=l&&r<=r1) { tree[a].w+=w1; tree[a].lz+=w1; return ; } int mid=(l+r)>>1; if(tree[a].lz) Push_down(a); if(l1<=mid) Update(l,mid,l1,r1,w1,a<<1); if(r1>mid) Update(mid+1,r,l1,r1,w1,a<<1|1); Push_up(a); } ll Ques(int l,int r,int l1,int r1,int a) { ll mx=-inf; if(l1<=l&&r<=r1) { return tree[a].w; } int mid=(l+r)>>1; if(tree[a].lz) Push_down(a); if(l1<=mid) mx=max(mx,Ques(l,mid,l1,r1,a<<1)); if(r1>mid) mx=max(mx,Ques(mid+1,r,l1,r1,a<<1|1)); return mx; } int main() { int t,ca; ca=1; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); cnt=0; for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } for(int i=0;i<n;i++) scanf("%I64d",&w[i]); num=0; dis[0]=w[0]; dfs(0,-1); Build(1,num,1); printf("Case #%d: ",ca++); while(m--) { int way; scanf("%d",&way); if(way==1) { int a; scanf("%I64d",&a); printf("%I64d ",Ques(1,n,ls[a],rs[a],1)); } else { int a; ll b; scanf("%d%I64d",&a,&b); Update(1,n,ls[a],rs[a],b-w[a],1); w[a]=b; } } } return 0; }