bzoj3052糖果公园

来源:互联网 发布:pci e视频采集卡 编程 编辑:程序博客网 时间:2024/04/28 08:50

树上修改莫队算法

非常好的一道题,其实应该把部分分都写一次

前30分是送的

50分是最普通的莫队算法

70分是clj的选择,也就是树上不修改莫队

100分是树上修改莫队


其实我昨天晚上睡觉的时候意识到第二天要很早起来写糖果公园但是还是没有意识到这个题的恶心之处,第一次写完貌似有9k。。。

然后赶紧缩,最后好不容易到了7k左右,不记得了。。。

很经典很神的算法,只不过因为程序太长了所以我不得不采用和标程对拍中间结果的办法来检查程序,如果这是在考场上那么我会毫不犹豫的选择哪个50分


不得不说艾神的题很复杂,而且我也看了vfk的题解。。。。

就这么多吧,似乎看了题解的人没资格讲做法,具体的去看vfk

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#define Size (int)pow(n,2.0/3)#define MAX 200010#define ll long longusing namespace std;int n,m,k,ind,BlockSize=0;int cnt[MAX],pos[MAX];int deep[MAX];ll ans;bool vis[MAX]={0};int father[MAX],f[MAX][20];int logg[MAX];int wait[MAX],waitting=0;ll val1[MAX],val2[MAX];vector<int>candy[MAX];vector<int>edge[MAX];vector<int>::iterator now[MAX];struct wbysr_change{int a,b;}op[MAX];struct wbysr{int l,r,id;ll ans;}ask[MAX];void debug_(){for(int i=1;i<=n;i++){printf("----%d\n",i);for(int j=0;j<edge[i].size();j++)printf("%d ",edge[i][j]);printf("\n");for(int j=0;j<candy[i].size();j++)printf("%d ",candy[i][j]);printf("\n");}//printf("debug done\n");for(int i=1;i<=n;i++)printf("%d %d\n",i,pos[i]);}int dfs(int x){//printf("fuck %d\n",x);int sum=0;/*for(int i=0;i<edge[x].size();i++)if(!deep[i]){father[i]=x;deep[i]=deep[x]+1;f[i][0]=x;for(int j=1;j<=18;j++)f[i][j]=f[f[i][j-1]][j-1];sum+=dfs(i);if(sum>=Size){BlockSize++;while(sum--)pos[wait[waitting--]]=BlockSize;sum=0;}}*////*for(vector<int>::iterator i=edge[x].begin();i!=edge[x].end();i++)if(0==deep[*i]){father[*i]=x;deep[*i]=deep[x]+1;f[*i][0]=x;for(int j=1;j<=18;j++)f[*i][j]=f[f[*i][j-1]][j-1];sum+=dfs(*i);if(sum>=Size){BlockSize++;while(sum--)pos[wait[waitting--]]=BlockSize;//printf("ooooooooooo%d %d\n",wait[waitting+1],pos[wait[waitting+1]]);sum=0;}}//*/wait[++waitting]=x;return ++sum;}bool sort_ask(wbysr a1,wbysr a2){if(pos[a1.l]!=pos[a2.l])return pos[a1.l]<pos[a2.l];elseif(pos[a1.r]!=pos[a2.r])return pos[a1.r]<pos[a2.r];return a1.id<a2.id;}void init(){scanf("%d%d%d",&n,&m,&k);//readfor(int i=1;i<=m;i++)scanf("%lld",&val1[i]);for(int i=1;i<=n;i++)scanf("%lld",&val2[i]);for(int i=1,a1,a2;i<=n-1;i++){scanf("%d%d",&a1,&a2);edge[a1].push_back(a2);edge[a2].push_back(a1);}for(int i=1,w;i<=n;i++){scanf("%d",&w);candy[i].push_back(w);}ind=0;for(int i=1,c;i<=k;i++){scanf("%d",&c);if(0==c){scanf("%d%d",&op[i].a,&op[i].b);candy[op[i].a].push_back(op[i].b);}else{ind++;scanf("%d%d",&ask[ind].l,&ask[ind].r);ask[ind].id=i;//printf("====================%d %d\n",ask[ind].l,ask[ind].r);}}//printf("sfddddddddd\n");//before donefor(int i=1;i<=n;i++)now[i]=candy[i].begin();deep[1]=1;dfs(1);//printf("888888888888888888888\n");//while(waitting)//pos[wait[waitting--]]=BlockSize;for(int i=2;i<=n;i++)logg[i]=logg[i-1]+(i==(i&-i));//for(int i=1;i<=ind;i++)//if(pos[ask[i].l]>pos[ask[i].r])//swap(ask[i].l,ask[i].r);sort(ask+1,ask+1+ind,sort_ask);//debug();//for(int i=1;i<=ind;i++)//printf("++++++++++++++++++%d %d\n",ask[i].l,ask[i].r);}void xor_point(int x){if(vis[x]){int c=*now[x];ans-=val1[c]*val2[cnt[c]];cnt[c]--;vis[x]=0;//ans+=val1[c]*val2[cnt[c]];}else{int c=*now[x];cnt[c]++;ans+=val1[c]*val2[cnt[c]];vis[x]=1;//ans-=val1[c]*val2[cnt[c]];}return;}void xor_path(int a,int b){if(deep[a]<deep[b])swap(a,b);while(deep[a]!=deep[b]){xor_point(a);a=father[a];}while(a!=b){xor_point(a);xor_point(b);a=father[a];b=father[b];}}int LCA(int a,int b){//printf("LCA begin\n");if(deep[a]<deep[b])swap(a,b);for(int i=logg[deep[a]];i>=0;i--)if(deep[f[a][i]]>=deep[b])a=f[a][i];if(a==b)return a;for(int i=logg[deep[a]];i>=0;i--)if(f[a][i]!=f[b][i]){a=f[a][i];b=f[b][i];}//printf("LCA end\n");return father[a];}ll work(int a,int b){int lca=LCA(a,b);//printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%d %d %d\n",a,b,lca);xor_point(lca);ll tot=ans;//printf("%lld\n",tot);xor_point(lca);return tot;}void captail_mo(){for(int i=1,l=1,r=1,time=0;i<=ind;i++){//printf("%d %d %d %d %d\n",ask[i].id,ask[i].l,ask[i].r,l,r);while(time<ask[i].id){int p=op[++time].a;if(!p)continue;bool flag=vis[p];if(flag)xor_point(p);++now[p];if(flag)xor_point(p);}while(time>ask[i].id){int p=op[time--].a;if(!p)continue;bool flag=vis[p];if(flag)xor_point(p);now[p]--;if(flag)xor_point(p);}xor_path(l,ask[i].l);xor_path(r,ask[i].r);l=ask[i].l;r=ask[i].r;//printf("MO\n");ask[i].ans=work(l,r);}}bool cmp_end(wbysr a1,wbysr a2){return a1.id<a2.id;}void print(){sort(ask+1,ask+1+ind,cmp_end);for(int i=1;i<=ind;i++)printf("%lld\n",ask[i].ans);return;}void da(){for(int i=1;i<=k;i++)if(ask[i].l>ask[i].r)swap(ask[i].l,ask[i].r);return;}int main(){init();//printf("------------------init\n");//da();captail_mo();//printf("------------------captail_mo");print();return 0;}

0 0