[BZOJ2164]采矿

题目描述

浩浩荡荡的\(cg\)大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略。

这个城市可以看成一棵有\(n\)个节点的有根树,我们把每个节点用1到n的整数编号。

为了方便起见,对于任何一个非根节点\(v\),它任何一个祖先的编号都严格小于\(v\)

树上的每个节点表示一个矿点,每条边表示一条街道.

作为\(cg\)大军的一个小队长,你拥有\(m\)个部下。

你有一张二维的动态信息表,用\(T_{i,j}\)表示第\(i\)行第\(j\)列的数据。

当你被允许开采某个区域时,你可以将你的部下分配至各个矿点。

在第\(i\)个矿点安排\(j\)个人可以获得\(T{i,j}\)单位的矿产。

允许开采的区域是这样描述的:给你一对矿点\((u,v)\),保证\(v\)\(u\)的祖先(这里定义祖先包括\(u\)本身);\(u\)为你控制的区域,可以在以\(u\)为根的子树上任意分配部下;\(u\)\(v\)的简单路径(不包括\(u\)但包括\(v\),若\(u=v\)则包括\(u\))为探险路径,在该路径上你可以选择至多一个矿点安排部下。你这次开采的收益为安排有部下的矿点的收益之和。

Input

输入的第一行包含\(5\)个正整数\(n、m、A、B、Q。n\)为矿点的个数,\(m\)为部下的数量,\(A、B、Q\)是与动态信息表有关的数据。

第二行包含\(n-1\)个正整数,第\(i\)个数为\(F_{i+1}\),表示节点\(i+1\)的父亲。

接下来需要你用下文的方法依次生成\(n\)组数据,每组数据共\(m\)个。

其中第\(i\)组的\(m\)个数据为信息表中第\(i\)行的\(m\)个数据。

紧接着一行包含一个正整数\(C\),表示事件的数量。

最后给出\(C\)行,每行描述一个事件。

每个事件会先给出一个\(0\)\(1\)的整数。

如果该数为\(0\),则后面有一个正整数\(p\),表示动态信息表有更新,你需要生成一组\(m\)个数据,来替换信息表中第\(p\)行的\(m\)个数据。

如果该数为\(1\),则后面有两个正整数\(u、v\),表示出现了一个你可以开采的区域,你需要回答这次开采的收益。同一行的各个数之间均用一个空格隔开,没有多余的空格和换行。

数据的生成方法如下:每次生成一组\(m\)个从小到大排列的数据,替换动态信息表的一行。其中,从小到大第\(j\)个数替换信息表中第\(j\)列的数。调用以下代码\(m\)次并排序得到一组数据。(注意可能会出现重复的数)函数GetInt A←((A xor B)+(B div X)+(B * X))and Y B←((A xor B)+(A div X)+(A * X))and Y 返回(A xor B)mod Q ,\(X=2^{16}\)(2的16次方),\(Y=2^{31}-1\)(2的31次方-1),xor为位异或运算,div为整除运算,and为位且运算,mod为取余运算。由于只保留了低31位,易得我们不用考虑数据的溢出问题。(注意每次A和B都会被改变)

对于\(100\%\)的数据\(1≤n≤20000,1≤m≤50,1≤C≤2000\)。对于满足\(2≤i≤n\)的整数\(i,1≤F_i<i。1≤A,B≤2^{31}-1,1≤Q≤10000\)

Output

包括一个非负整数,表示有多少种放置的方案.

Sample Input

10 5 1 2 10
1 1 3 3 4 4 6 6 9
4
1 6 3
1 9 1
0 1
1 1 1

Sample Output

11
9
12

个人觉得这道题和树形\(dp\)并没有什么关系。。。

比较显然的就是这题的暴力\(dp\),我们只需要知道题目给出的\(T_{i,j}\)就可以进行背包的转移了。

题目中的多个矿点的抉择,我们就是利用背包的转移方式进行转移即可。

题目给出了两个限制条件。

1.子树内。

这个我们可以直接暴力\(m^2\)合并两个矿点,\(dfs\)序将其变成一个区间,暴力合并\(L[x]-R[x]\)利用合并完的\(dp\)进行\(dp\)即可。

2.有一条链。

那个唯一剩下的链我们可以直接对于\(Fa[u]-v\)中所有的矿点取一个\(max\)

现在最大的问题就是这是一个动态的问题,那么我们就可以直接用动态树上问题的基本数据结构-树链剖分。

我们将树进行树剖,对于子树的一段区间我们维护合并后的\(dp\),这个我们可以利用线段数维护。

然后,对于剩下的一条链,我们可以跳重链取一个\(max\),最后将其和子树的区间进行合并即可。

时间复杂度为预处理复杂度\(O(n*log_n*m^2)\)+单次复杂度\(O(m^2*log_n)≈\)\(O(n*log_n*m^2)\)

include <bits/stdc++.h>
 
using namespace std;
 
#define int long long
#define reg register
#define Raed Read
#define clr(a,b) memset(a,b,sizeof a)
#define Mod(x) (x>=mod)&&(x-=mod)
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
 
inline int Read(void) {
    int res=0,f=1;
    char c;
    while(c=getchar(),c<48||c>57)if(c=='-')f=0;
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>=48&&c<=57);
    return f?res:-res;
}
 
template<class T>inline bool Min(T &a, T const&b) {
    return a>b?a=b,1:0;
}
template<class T>inline bool Max(T &a, T const&b) {
    return a<b?a=b,1:0;
}
const int N=2e4+5,M=2e4+5,X=65536,Y=2147483647;
 
bool MOP1;
 
int n,m,A,B,Q;
 
int us[55],val[N][55];
 
inline int Function(void) {
    A=((A^B)+(B/X)+(B*X))&Y;
    B=((A^B)+(A/X)+(A*X))&Y;
    return (A^B)%Q;
}
 
struct node {
    int dp[55];
    void clear(void) {
        clr(dp,0);
    }
    inline node operator+(node _)const {
        node res;
        res.clear();
        rep(i,0,m)res.dp[i]=max(dp[i],_.dp[i]);
        return res;
    }
    inline node operator*(node _)const {
        node res;
        res.clear();
        rep(i,0,m)rep(j,0,m)if(i+j<=m)Max(res.dp[i+j],_.dp[i]+dp[j]);
        return res;
    }
} E[N];
 
struct Link_list {
    int Tot,Head[N],to[M<<1],Nxt[M<<1];
    inline void clear(void) {
        Tot=0,clr(Head,0);
    }
    inline void AddEdgepair(int a,int b) {
        to[++Tot]=b,Nxt[Tot]=Head[a],Head[a]=Tot;
        to[++Tot]=a,Nxt[Tot]=Head[b],Head[b]=Tot;
    }
} G;
 
int Fa[N],dep[N],Sz[N],son[N];
void dfs1(int x,int pre) {
    Sz[x]=1,Fa[x]=pre,dep[x]=dep[pre]+1;
    erep(i,G,x) {
        int y=G.to[i];
        if(y==pre)continue;
        dfs1(y,x),Sz[x]+=Sz[y];
        (Sz[y]>Sz[son[x]])&&(son[x]=y);
    }
}
 
int L[N],R[N],top[N],Id[N],cnt;
void dfs2(int x,int tp) {
    top[x]=tp,L[x]=++cnt;
    Id[cnt]=x;
    if(son[x])dfs2(son[x],tp);
    erep(i,G,x) {
        int y=G.to[i];
        if(y==Fa[x]||y==son[x])continue;
        dfs2(y,y);
    }
    R[x]=cnt;
}
 
struct Seg {
    node Tr1[N<<2],Tr2[N<<2];
    inline void up(int num) {
        Tr1[num]=Tr1[num<<1]*Tr1[num<<1|1];
        Tr2[num]=Tr2[num<<1]+Tr2[num<<1|1];
    }
    void build(int L,int R,int num) {
        if(L==R) {
            Tr1[num]=Tr2[num]=E[Id[L]];
            return;
        }
        int mid=(L+R)>>1;
        build(L,mid,num<<1);
        build(mid+1,R,num<<1|1);
        up(num);
    }
    void update(int L,int R,int num,int op,node x) {
        if(L==R) {
            Tr1[num]=Tr2[num]=x;
            return;
        }
        int mid=(L+R)>>1;
        if(op<=mid)update(L,mid,num<<1,op,x);
        else update(mid+1,R,num<<1|1,op,x);
        up(num);
    }
    node query1(int L,int R,int num,int l,int r) {
        if(L==l&&R==r)return Tr1[num];
        int mid=(L+R)>>1;
        if(r<=mid)return query1(L,mid,num<<1,l,r);
        else if(l>mid)return query1(mid+1,R,num<<1|1,l,r);
        return query1(L,mid,num<<1,l,mid)*query1(mid+1,R,num<<1|1,mid+1,r);
    }
    node query2(int L,int R,int num,int l,int r) {
        if(L==l&&R==r)return Tr2[num];
        int mid=(L+R)>>1;
        if(r<=mid)return query2(L,mid,num<<1,l,r);
        else if(l>mid)return query2(mid+1,R,num<<1|1,l,r);
        return query2(L,mid,num<<1,l,mid)+query2(mid+1,R,num<<1|1,mid+1,r);
    }
} tr;
 
bool MOP2;
 
void _main(void) {
    n=Read(),m=Read(),A=Read(),B=Read(),Q=Read();
    rep(i,1,n) {
        rep(j,1,m)us[j]=Function();
        sort(us+1,us+m+1);
        E[i].clear();
        rep(j,1,m)E[i].dp[j]=us[j];
    }
    rep(i,2,n) {
        int F=Read();
        G.AddEdgepair(F,i);
    }
    dfs1(1,-1),dfs2(1,1);
    tr.build(1,n,1);
    int C=Read();
    rep(i,1,C) {
        int op=Read();
        if(!op) {
            int p=Read();
            rep(j,1,m)us[j]=Function();
            sort(us+1,us+m+1);
            node Now;
            Now.clear();
            rep(j,1,m)Now.dp[j]=us[j];
            tr.update(1,n,1,L[p],Now);
        } else {
            int u=Read(),v=Read(),Ans=0;
            node L1=tr.query1(1,n,1,L[u],R[u]),R1;
            R1.clear();
            if(u!=v) {
                int x=Fa[u],y=v;
                while(top[x]!=top[y]) {
                    R1=R1+tr.query2(1,n,1,L[top[x]],L[x]);
                    x=Fa[top[x]];
                }
                R1=R1+tr.query2(1,n,1,L[y],L[x]);
            }
            L1=L1*R1;
            printf("%lld\n",L1.dp[m]);
        }
    }
}
 
signed main() {
    _main();
    return 0;
}
posted @ 2019-09-08 22:21  dsjkafdsaf  阅读(176)  评论(0编辑  收藏  举报