zoukankan      html  css  js  c++  java
  • Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    【题目链接】

        http://www.tsinsen.com/A1219

    【题意】

        给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u->v(不含u)路径上的节点分配人数的最优收益。

    【思路】

        树链剖分:构造重链时先访问重儿子,因此一个重链的区间连续,同时一个子树的区间连续。

        查询分为两部分:构造在u子树内分配人数i的最大收益ans1[i],以及构造在u->v路径上一个结点分配人数i的最大收益ans2[i]。则ans=max{ ans1[i]+ans2[m-i] }。

        考虑链剖:一棵线段树维护一条重链上的两类信息,c[i]为任意分配的最优,g[i]为在其中一个分配的最优。则ans1可以通过询问u子树的连续区间得,ans2可以询问u->v路径上的重链得。

        需要注意的是线段树中c的递推应该逆序枚举,否则覆盖原值。

    【代码】

      1 #include<set>
      2 #include<cmath>
      3 #include<queue>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
     10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 const int N = 4e4+10;
     15 const int M = 55;
     16 const ll X = 1<<16;
     17 const ll Y = 2147483647; 
     18 
     19 ll read() {
     20     char c=getchar();
     21     ll f=1,x=0;
     22     while(!isdigit(c)) {
     23         if(c=='-') f=-1; c=getchar();
     24     }
     25     while(isdigit(c))
     26         x=x*10+c-'0',c=getchar();
     27     return x*f;
     28 }
     29 
     30 struct Edge {
     31     int v,nxt;
     32 }e[N<<1];
     33 int en=1,front[N];
     34 void adde(int u,int v) 
     35 {
     36     e[++en]=(Edge){v,front[u]}; front[u]=en;
     37 }
     38 
     39 int n,m,C,a[N][M],dfs_list[N],SZ,dfn; ll A,B,Q;
     40 int dep[N],son[N],top[N],siz[N],fa[N],pl[N],L[N],R[N];
     41 
     42 struct Tnode {
     43     int u,l,r,c[M],g[M];
     44     void maintain() ;
     45 } T[N<<1];
     46 void Tnode::maintain() {
     47     if(T[u].l==T[u].r) return ;
     48     memset(c,0,sizeof(c));
     49     FOR(i,0,m) FOR(j,0,m-i)
     50         c[i+j]=max(c[i+j],T[u<<1].c[i]+T[u<<1|1].c[j]);
     51     FOR(i,0,m) 
     52         g[i]=max(T[u<<1].g[i],T[u<<1|1].g[i]);
     53 }
     54 
     55 void build(int u,int l,int r)
     56 {
     57     T[u].u=u,T[u].l=l,T[u].r=r;
     58     if(l==r) {
     59         memcpy(T[u].c,a[dfs_list[l]],sizeof(T[u].c));
     60         memcpy(T[u].g,a[dfs_list[l]],sizeof(T[u].g));
     61         return ;
     62     }
     63     int mid=l+r>>1;
     64     build(u<<1,l,mid);
     65     build(u<<1|1,mid+1,r);
     66     T[u].maintain();
     67 }
     68 void update(int u,int x,int* A)
     69 {
     70     if(T[u].l==T[u].r) {
     71         memcpy(T[u].c,A,sizeof(T[u].c));
     72         memcpy(T[u].g,A,sizeof(T[u].g));
     73     } else {
     74         int mid=T[u].l+T[u].r>>1;
     75         if(x<=mid) update(u<<1,x,A);
     76         else update(u<<1|1,x,A);
     77         T[u].maintain();
     78     }
     79 }
     80 void query1(int u,int L,int R,int* ans)
     81 {
     82     if(L<=T[u].l&&T[u].r<=R) {
     83         for(int i=m;i;i--) for(int j=i;j;j--)        //逆序枚举i 避免覆盖 
     84             ans[i]=max(ans[i],ans[i-j]+T[u].c[j]);
     85     } else {
     86         int mid=T[u].l+T[u].r>>1;
     87         if(L<=mid) query1(u<<1,L,R,ans);
     88         if(mid<R) query1(u<<1|1,L,R,ans);
     89     }
     90 }
     91 void query2(int u,int L,int R,int* ans)
     92 {
     93     if(L<=T[u].l&&T[u].r<=R) {
     94         FOR(i,0,m) ans[i]=max(ans[i],T[u].g[i]);
     95     } else {
     96         int mid=T[u].l+T[u].r>>1;
     97         if(L<=mid) query2(u<<1,L,R,ans);
     98         if(mid<R) query2(u<<1|1,L,R,ans);
     99     }
    100 }
    101 
    102 void dfs1(int u) 
    103 {
    104     siz[u]=1; son[u]=0;
    105     trav(u,i) if(e[i].v!=fa[u]) {
    106         int v=e[i].v;
    107         fa[v]=u;
    108         dep[v]=dep[u]+1;
    109         dfs1(v);
    110         siz[u]+=siz[v];
    111         if(siz[v]>siz[son[u]]) son[u]=v;
    112     }
    113 }
    114 void dfs2(int u,int tp) 
    115 {
    116     top[u]=tp; pl[u]=L[u]=++SZ; dfs_list[SZ]=u;
    117     if(son[u]) dfs2(son[u],tp);
    118     trav(u,i) if(e[i].v!=fa[u]&&e[i].v!=son[u])
    119         dfs2(e[i].v,e[i].v);
    120     R[u]=SZ;
    121 }
    122 void query2(int u,int v,int*ans)
    123 {
    124     while(top[u]!=top[v]) {
    125         if(dep[top[u]]<dep[top[v]]) swap(u,v);
    126         query2(1,pl[top[u]],pl[u],ans);
    127         u=fa[top[u]];
    128     }
    129     if(dep[u]>dep[v]) swap(u,v);
    130     query2(1,pl[u],pl[v],ans);
    131 }
    132 
    133 int get_int()
    134 {
    135     A=((A^B)+(B/X)+(ll)(B*X))&Y;
    136     B=((A^B)+(A/X)+(ll)(A*X))&Y;
    137     return (int)(A^B)%Q;
    138 }
    139 
    140 int ans1[M],ans2[M];
    141 
    142 int main()
    143 {
    144 //    freopen("in.in","r",stdin);
    145 //    freopen("out.out","w",stdout);
    146     n=read(),m=read(),A=read(),B=read(),Q=read();
    147     int op,u,v;
    148     FOR(i,2,n) {
    149         u=read(); adde(u,i);
    150     }
    151     FOR(i,1,n) {
    152         FOR(j,1,m) a[i][j]=get_int();
    153         sort(a[i]+1,a[i]+m+1);
    154     }
    155     dfs1(1); dfs2(1,1);
    156     build(1,1,SZ);
    157     C=read();
    158     FOR(i,1,C) {
    159         op=read(),u=read();
    160         if(op==0) {
    161             FOR(j,1,m) a[u][j]=get_int();
    162             sort(a[u]+1,a[u]+m+1);
    163             update(1,L[u],a[u]);
    164         } else {
    165             v=read();
    166             memset(ans1,0,sizeof(ans1));
    167             memset(ans2,0,sizeof(ans2));
    168             query1(1,L[u],R[u],ans1);
    169             if(u!=v) query2(fa[u],v,ans2);
    170             int ans=0;
    171             FOR(i,0,m)
    172                 ans=max(ans,ans1[i]+ans2[m-i]);
    173             printf("%d
    ",ans); 
    174         }
    175     }
    176     return 0;
    177 }

    P.S.拿线段树DP,这道题实在是太太太太太神辣

  • 相关阅读:
    正则表达式体会
    checkbox、全选反选,获取值
    弹出窗体值回调
    页面点击任意js事件,触发360、IE浏览器新页面
    XML增、删、改
    面试题
    行列转换
    DataTable 和Json 字符串互转
    前台js与后台方法互调
    文件与base64二进制转换
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5325940.html
Copyright © 2011-2022 走看看