码迷,mamicode.com
首页 > 其他好文 > 详细

【xsy2440】【GDOI2016】疯狂动物城

时间:2018-06-25 11:14:03      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:IV   线段树   next   space   fine   ace   efi   class   swa   

技术分享图片

技术分享图片

技术分享图片

感受一下这恐怖的题目长度~~~

其实题意很裸,但是作为GDOI的一道防AK题,自然有他优秀的地方。

简化题意:给出一棵树,要求支持三个操作:

1.修改点值

2.询问点$x$到$y$之间的一些东东

3.回到某个版本之前

可持久化,强制在线。

考虑拆一下询问

如果把$x$到$y$路径上的所有点值放到一个数组$a$里,那么询问式子就是:

$\sum\limits_{i=1}^{n}a[i]\times\sum\limits_{j=1}^{n-i}j$

$=\sum\limits_{i=1}^{n}a[i]\times\frac{(n-i+1)\times(n-i)}{2}$

$=\sum\limits_{i=1}^{n}a[i]\times i^{2}-a[i]\times(2n+1)+a[i]\times n\times(n+1)$

发现$a[i]$,$a[i]\times i$,$a[i]\times i^2$都是常系数,于是就可以快乐维护了~

外面的很容易想到,树链剖分+可持久化线段树,单点修改即可。

可以感觉到逐渐膨胀的代码量>_<

注意到有左右方向的区别,要写两遍

代码量起飞了>_<

5000B刷新最长代码记录

注意:记得取模,随时爆int;

 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #define mod 20160501
  6 using namespace std;
  7 typedef long long ll;
  8 struct edge{
  9     int v,next;
 10 }a[500001];
 11 struct data{
 12     ll s,a1,a2,s1,s2,ls,rs,lz,vv;
 13 }t[5000001];
 14 ll n,m,u,v,w,ord,tim=0,tot=0,tote=0,ans=0,nrt=0,nowrt=0,last=0,ans1[2],ans2[2],head[1000001],rt[1000001],num[1000001],nmd[1000001],dep[1000001],top[1000001],siz[1000001],dfn[1000001],son[1000001],fa[1000001];
 15 void add(int u,int v){
 16     a[++tote].v=v;
 17     a[tote].next=head[u];
 18     head[u]=tote;
 19 }
 20 void dfs1(int u,int f,int dpt){
 21     fa[u]=f;
 22     dep[u]=dpt;
 23     siz[u]=1;
 24     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 25         int v=a[tmp].v;
 26         if(v==f)continue;
 27         dfs1(v,u,dpt+1);
 28         siz[u]+=siz[v];
 29         if(son[u]==-1||siz[v]>siz[son[u]])son[u]=v;
 30     }
 31 }
 32 void dfs2(int u,int nowtp){
 33     top[u]=nowtp;
 34     dfn[u]=++tim;
 35     nmd[tim]=u;
 36     if(son[u]==-1)return;
 37     dfs2(son[u],nowtp);
 38     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
 39         int v=a[tmp].v;
 40         if(v==son[u]||v==fa[u])continue;
 41         dfs2(v,v);
 42     }
 43 }
 44 void pushup(int u){
 45     t[u].s=(t[t[u].ls].s+t[t[u].rs].s)%mod;
 46     t[u].a1=(t[t[u].ls].a1+t[t[u].rs].a1)%mod;
 47     t[u].a2=(t[t[u].ls].a2+t[t[u].rs].a2)%mod;
 48     t[u].s1=(t[t[u].ls].s1+t[t[u].rs].s1)%mod;
 49     t[u].s2=(t[t[u].ls].s2+t[t[u].rs].s2)%mod;
 50 }
 51 void build(int l,int r,int u){
 52     if(l==r){
 53         t[u].s=num[nmd[l]];
 54         t[u].a1=dep[nmd[l]];
 55         t[u].a2=(t[u].a1*t[u].a1)%mod;        
 56         t[u].s1=(t[u].s*t[u].a1)%mod;
 57         t[u].s2=(t[u].s*t[u].a2)%mod;
 58         return;
 59     }
 60     int mid=(l+r)/2;
 61     build(l,mid,t[u].ls=++tot);
 62     build(mid+1,r,t[u].rs=++tot);
 63     pushup(u);
 64 }
 65 void updata(int l,int r,int u,int L,int R,int lst,ll v){
 66     if(u==tot)t[u]=t[lst];
 67     if(l==L&&r==R){
 68         t[u].ls=t[lst].ls;
 69         t[u].rs=t[lst].rs;
 70         t[u].lz=(t[u].lz+v)%mod;
 71         t[u].s1=(t[u].s1+t[u].a1*v)%mod;
 72         t[u].s2=(t[u].s2+t[u].a2*v)%mod;
 73         t[u].s=(t[u].s+v*(r-l+1))%mod;
 74         t[u].vv=(t[u].vv+v)%mod;
 75         return;
 76     }
 77     int mid=(l+r)/2;
 78     if(R<=mid){
 79         if(t[u].rs<=last)t[u].rs=t[lst].rs;
 80         if(t[u].ls<=last)t[u].ls=++tot;
 81         updata(l,mid,t[u].ls,L,R,t[lst].ls,v);
 82     }else if(mid<L){
 83         if(t[u].ls<=last)t[u].ls=t[lst].ls;
 84         if(t[u].rs<=last)t[u].rs=++tot;
 85         updata(mid+1,r,t[u].rs,L,R,t[lst].rs,v);
 86     }else{
 87         if(t[u].ls<=last)t[u].ls=++tot;
 88         updata(l,mid,t[u].ls,L,mid,t[lst].ls,v);
 89         if(t[u].rs<=last)t[u].rs=++tot;
 90         updata(mid+1,r,t[u].rs,mid+1,R,t[lst].rs,v);
 91     }
 92     t[u].s1=(t[t[u].ls].s1+t[t[u].rs].s1+t[u].a1*t[u].vv%mod)%mod;
 93     t[u].s2=(t[t[u].ls].s2+t[t[u].rs].s2+t[u].a2*t[u].vv%mod)%mod;
 94     t[u].s=(t[t[u].ls].s+t[t[u].rs].s+t[u].vv*(r-l+1)%mod)%mod;
 95 }
 96 void getans(int u,int b,ll lz,ll v){
 97     ans=(ans+t[u].s2+lz*t[u].a2%mod)%mod;
 98     ans1[b]=(ans1[b]+t[u].s1+t[u].a1*lz%mod)%mod;
 99     ans2[b]=(ans2[b]+t[u].s+v*lz%mod)%mod;
100 }
101 void query(int l,int r,int u,int L,int R,int b,ll lz){
102     if(!u)return;
103     lz+=t[u].vv;
104     if(l==L&&r==R){
105         lz-=t[u].lz;
106         getans(u,b,lz,r-l+1);
107         return;
108     }
109     int mid=(l+r)/2;
110     if(R<=mid)query(l,mid,t[u].ls,L,R,b,lz);
111     else if(mid<L)query(mid+1,r,t[u].rs,L,R,b,lz);
112     else{
113         query(l,mid,t[u].ls,L,mid,b,lz);
114         query(mid+1,r,t[u].rs,mid+1,R,b,lz);
115     }
116 }
117 void work(int t,int t1,int u,int v,ll w){
118     while(top[u]!=top[v]){
119         if(dep[top[u]]<dep[top[v]])swap(u,v);
120         updata(1,n,rt[t],dfn[top[u]],dfn[u],rt[t1],w);
121         u=fa[top[u]];
122     }
123     if(dep[u]>dep[v])swap(u,v);
124     updata(1,n,rt[t],dfn[u],dfn[v],rt[t1],w);
125 }
126 int work1(int t,int u,int v){
127     while(top[u]!=top[v]){
128         if(dep[top[u]]>dep[top[v]]){
129             query(1,n,rt[t],dfn[top[u]],dfn[u],0,0);
130             u=fa[top[u]];
131         }else{
132             query(1,n,rt[t],dfn[top[v]],dfn[v],1,0);
133             v=fa[top[v]];
134         }
135     }
136     if(dep[u]>dep[v]){
137         query(1,n,rt[t],dfn[v],dfn[u],0,0);
138         return v;
139     }else{
140         query(1,n,rt[t],dfn[u],dfn[v],1,0);
141         return u;
142     }
143 }
144 int main(){
145     memset(son,-1,sizeof(son));
146     memset(head,-1,sizeof(head));
147     scanf("%lld%lld",&n,&m);
148     for(int i=1;i<n;i++){
149         scanf("%lld%lld",&u,&v);
150         add(u,v);
151         add(v,u);
152     }
153     for(int i=1;i<=n;i++)scanf("%lld",&num[i]);
154     dfs1(1,0,1);
155     dfs2(1,1);
156     rt[0]=tot=1;
157     build(1,n,rt[0]);
158     for(int i=1;i<=m;i++){
159         scanf("%lld",&ord);
160         if(ord==1){
161             scanf("%lld%lld%lld",&u,&v,&w);
162             u^=ans;
163             v^=ans;
164             last=tot;
165             rt[++nrt]=++tot;
166             work(nrt,nowrt,u,v,w);
167             nowrt=nrt;
168         }else if(ord==2){
169             scanf("%lld%lld",&u,&v);
170             u^=ans;
171             v^=ans;
172             ans=ans1[0]=ans1[1]=ans2[0]=ans2[1]=0;
173             int t=dep[v]-dep[work1(nowrt,u,v)]*2;
174             ans=(ans+ans1[0]*(t*2+1)%mod+ans2[0]*t%mod*(t+1)%mod)%mod;
175             ans=(ans-ans1[1]*(dep[v]*2+1)%mod+ans2[1]*dep[v]%mod*(dep[v]+1)%mod+mod)%mod;
176             ans=(ans*10080251)%(ll)mod;
177             ans=(ans+mod)%mod;
178             printf("%lld\n",ans);
179         }else{
180             scanf("%lld",&u);
181             u^=ans;
182             nowrt=u;
183         }
184     }
185     return 0;
186 } 

 

【xsy2440】【GDOI2016】疯狂动物城

标签:IV   线段树   next   space   fine   ace   efi   class   swa   

原文地址:https://www.cnblogs.com/dcdcbigbig/p/9222650.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!