记录编号 | 236418 | 评测结果 | AAAAAAAAAAAAAAAAAAAA | ||
---|---|---|---|---|---|
题目名称 | [国家集训队2011]采矿 | 最终得分 | 100 | ||
用户昵称 | 是否通过 | 通过 | |||
代码语言 | C++ | 运行时间 | 6.267 s | ||
提交时间 | 2016-03-14 08:06:44 | 内存使用 | 70.58 MiB | ||
#include<cstdio> #include<deque> #include<algorithm> #include<iostream> #include<cstring> using namespace std; const int SIZEM=60,SIZEN=20010; typedef long long LL; int N,M,A,B,Q; class miku { public: int l,r; int s[SIZEM]; int mx[SIZEM];//在这个区间内T[i][j]的最大值 int id[SIZEM]; void print() { for(int i=1;i<=M;i++) cout<<s[i]<<" "<<mx[i]<<" "<<id[i]<<endl; } }tr[SIZEN*4]; int top[SIZEN],w[SIZEN],siz[SIZEN],dep[SIZEN],f[SIZEN],pos[SIZEN]; int son[SIZEN];//重儿子 int totw,tot; deque<int> c[SIZEN]; int X=(1<<16),Y=(1<<31)-1; void add(int fr,int to){c[fr].push_back(to);} void read() { scanf("%d%d%d%d%d",&N,&M,&A,&B,&Q); f[1]=0; for(int i=1;i<N;i++) { scanf("%d",&f[i+1]); add(f[i+1],i+1); } } void dfs(int x)//树链剖分 { dep[x]=dep[f[x]]+1;siz[x]=1;son[x]=0; for(int i=0;i<c[x].size();i++) { int v=c[x][i]; dfs(v); siz[x]+=siz[v]; if(siz[v]>siz[son[x]]) son[x]=v; } } void maketree(int x,int tp) { pos[x]=++totw;top[x]=tp; if(son[x]) maketree(son[x],tp); for(int i=0;i<c[x].size();i++) { int v=c[x][i]; if(v==son[x]) continue; maketree(v,v); } } int T[SIZEN][SIZEM]={0}; int GetInt() { A=((A^B)+(B/X)+(B*X))&Y; B=((A^B)+(A/X)+(A*X))&Y; return (A^B)%Q; } void make(int root,int k) { T[k][0]=0; for(int i=1;i<=M;i++) T[k][i]=GetInt(); sort(T[k]+1,T[k]+M+1); for(int i=1;i<=M;i++) tr[root].mx[i]=tr[root].s[i]=T[k][i],tr[root].id[i]=k; } void update(int root) { for(int i=0;i<=M;i++) { tr[root].s[i]=0; for(int j=0;j<=i;j++) tr[root].s[i]=max(tr[root*2].s[j]+tr[root*2+1].s[i-j],tr[root].s[i]); if(tr[root*2].mx[i]>tr[root*2+1].mx[i]) tr[root].mx[i]=tr[root*2].mx[i],tr[root].id[i]=tr[root*2].id[i]; else tr[root].mx[i]=tr[root*2+1].mx[i],tr[root].id[i]=tr[root*2+1].id[i]; } } void seg_built(int root,int l,int r,int k) { if(r<k||l>k) return ; if(l==r) { make(root,k); return; } int mid=(l+r)/2; seg_built(root*2,l,mid,k); seg_built(root*2+1,mid+1,r,k); update(root); } void prepare() { dfs(1); maketree(1,1); for(int i=1;i<=N;i++) seg_built(1,1,totw,pos[i]); } class poi//临时的类 { public: //要不是为了减小常数我才不这样写呢 int s[SIZEM]; poi() { memset(s,0,sizeof(s)); } void add(poi a,poi b) { memset(s,0,sizeof(s)); for(int i=0;i<=M;i++) { for(int j=0 ;j<=i;j++) { s[i]=max(s[i],a.s[j]+b.s[i-j]); } } } }zero; poi get(int root,int lo,int hi,int l,int r) { if(hi<l||lo>r) return zero; if(l<=lo&&hi<=r){ poi A; for(int i=0;i<=M;i++) A.s[i]=tr[root].s[i]; return A; } int mid=(lo+hi)/2; poi A; A.add(get(root*2,lo,mid,l,r),get(root*2+1,mid+1,hi,l,r)); return A; } int getmx(int root,int lo,int hi,int l,int r,int cnt) { if(hi<l||lo>r) return 0; if(l<=lo&&hi<=r) { return tr[root].mx[cnt]; } int re=0; int mid=(lo+hi)/2; re=max(getmx(root*2,lo,mid,l,r,cnt),getmx(root*2+1,mid+1,hi,l,r,cnt)); return re; } int now=0; int find(int u,int v,int cnt) { int tem=0; int f1=top[u],f2=top[v]; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(f1,f2),swap(u,v); } tem=max(tem,getmx(1,1,totw,pos[f1],pos[u],cnt)); u=f[f1];f1=top[u]; } if(dep[u]>dep[v]) swap(u,v); tem=max(tem,getmx(1,1,totw,pos[u],pos[v],cnt)); return tem; } void calc(int u,int v) { poi ans1; ans1=get(1,1,totw,pos[u],pos[u]+siz[u]-1); int ans2[SIZEM]={0}; if(u!=v) { u=f[u]; for(int i=1;i<=M;i++) ans2[i]=find(u,v,i); } int ans=0; for(int i=0;i<=M;i++) ans=max(ans,ans1.s[i]+ans2[M-i]); printf("%d\n",ans); } void work() { int C; scanf("%d",&C); int cmd; int u,v; for(int i=1;i<=C;i++) { scanf("%d",&cmd); if(!cmd) { scanf("%d",&u); seg_built(1,1,totw,pos[u]); } else { now++; scanf("%d%d",&u,&v); calc(u,v); } } } int main() { freopen("mine.in","r",stdin); freopen("mine.out","w",stdout); read(); prepare(); work(); return 0; }