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

其实题意很裸,但是作为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;

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define mod 20160501
using namespace std;
typedef long long ll;
struct edge{
int v,next;
}a[];
struct data{
ll s,a1,a2,s1,s2,ls,rs,lz,vv;
}t[];
ll n,m,u,v,w,ord,tim=,tot=,tote=,ans=,nrt=,nowrt=,last=,ans1[],ans2[],head[],rt[],num[],nmd[],dep[],top[],siz[],dfn[],son[],fa[];
void add(int u,int v){
a[++tote].v=v;
a[tote].next=head[u];
head[u]=tote;
}
void dfs1(int u,int f,int dpt){
fa[u]=f;
dep[u]=dpt;
siz[u]=;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v==f)continue;
dfs1(v,u,dpt+);
siz[u]+=siz[v];
if(son[u]==-||siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int nowtp){
top[u]=nowtp;
dfn[u]=++tim;
nmd[tim]=u;
if(son[u]==-)return;
dfs2(son[u],nowtp);
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v==son[u]||v==fa[u])continue;
dfs2(v,v);
}
}
void pushup(int u){
t[u].s=(t[t[u].ls].s+t[t[u].rs].s)%mod;
t[u].a1=(t[t[u].ls].a1+t[t[u].rs].a1)%mod;
t[u].a2=(t[t[u].ls].a2+t[t[u].rs].a2)%mod;
t[u].s1=(t[t[u].ls].s1+t[t[u].rs].s1)%mod;
t[u].s2=(t[t[u].ls].s2+t[t[u].rs].s2)%mod;
}
void build(int l,int r,int u){
if(l==r){
t[u].s=num[nmd[l]];
t[u].a1=dep[nmd[l]];
t[u].a2=(t[u].a1*t[u].a1)%mod;
t[u].s1=(t[u].s*t[u].a1)%mod;
t[u].s2=(t[u].s*t[u].a2)%mod;
return;
}
int mid=(l+r)/;
build(l,mid,t[u].ls=++tot);
build(mid+,r,t[u].rs=++tot);
pushup(u);
}
void updata(int l,int r,int u,int L,int R,int lst,ll v){
if(u==tot)t[u]=t[lst];
if(l==L&&r==R){
t[u].ls=t[lst].ls;
t[u].rs=t[lst].rs;
t[u].lz=(t[u].lz+v)%mod;
t[u].s1=(t[u].s1+t[u].a1*v)%mod;
t[u].s2=(t[u].s2+t[u].a2*v)%mod;
t[u].s=(t[u].s+v*(r-l+))%mod;
t[u].vv=(t[u].vv+v)%mod;
return;
}
int mid=(l+r)/;
if(R<=mid){
if(t[u].rs<=last)t[u].rs=t[lst].rs;
if(t[u].ls<=last)t[u].ls=++tot;
updata(l,mid,t[u].ls,L,R,t[lst].ls,v);
}else if(mid<L){
if(t[u].ls<=last)t[u].ls=t[lst].ls;
if(t[u].rs<=last)t[u].rs=++tot;
updata(mid+,r,t[u].rs,L,R,t[lst].rs,v);
}else{
if(t[u].ls<=last)t[u].ls=++tot;
updata(l,mid,t[u].ls,L,mid,t[lst].ls,v);
if(t[u].rs<=last)t[u].rs=++tot;
updata(mid+,r,t[u].rs,mid+,R,t[lst].rs,v);
}
t[u].s1=(t[t[u].ls].s1+t[t[u].rs].s1+t[u].a1*t[u].vv%mod)%mod;
t[u].s2=(t[t[u].ls].s2+t[t[u].rs].s2+t[u].a2*t[u].vv%mod)%mod;
t[u].s=(t[t[u].ls].s+t[t[u].rs].s+t[u].vv*(r-l+)%mod)%mod;
}
void getans(int u,int b,ll lz,ll v){
ans=(ans+t[u].s2+lz*t[u].a2%mod)%mod;
ans1[b]=(ans1[b]+t[u].s1+t[u].a1*lz%mod)%mod;
ans2[b]=(ans2[b]+t[u].s+v*lz%mod)%mod;
}
void query(int l,int r,int u,int L,int R,int b,ll lz){
if(!u)return;
lz+=t[u].vv;
if(l==L&&r==R){
lz-=t[u].lz;
getans(u,b,lz,r-l+);
return;
}
int mid=(l+r)/;
if(R<=mid)query(l,mid,t[u].ls,L,R,b,lz);
else if(mid<L)query(mid+,r,t[u].rs,L,R,b,lz);
else{
query(l,mid,t[u].ls,L,mid,b,lz);
query(mid+,r,t[u].rs,mid+,R,b,lz);
}
}
void work(int t,int t1,int u,int v,ll w){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
updata(,n,rt[t],dfn[top[u]],dfn[u],rt[t1],w);
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
updata(,n,rt[t],dfn[u],dfn[v],rt[t1],w);
}
int work1(int t,int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]]){
query(,n,rt[t],dfn[top[u]],dfn[u],,);
u=fa[top[u]];
}else{
query(,n,rt[t],dfn[top[v]],dfn[v],,);
v=fa[top[v]];
}
}
if(dep[u]>dep[v]){
query(,n,rt[t],dfn[v],dfn[u],,);
return v;
}else{
query(,n,rt[t],dfn[u],dfn[v],,);
return u;
}
}
int main(){
memset(son,-,sizeof(son));
memset(head,-,sizeof(head));
scanf("%lld%lld",&n,&m);
for(int i=;i<n;i++){
scanf("%lld%lld",&u,&v);
add(u,v);
add(v,u);
}
for(int i=;i<=n;i++)scanf("%lld",&num[i]);
dfs1(,,);
dfs2(,);
rt[]=tot=;
build(,n,rt[]);
for(int i=;i<=m;i++){
scanf("%lld",&ord);
if(ord==){
scanf("%lld%lld%lld",&u,&v,&w);
u^=ans;
v^=ans;
last=tot;
rt[++nrt]=++tot;
work(nrt,nowrt,u,v,w);
nowrt=nrt;
}else if(ord==){
scanf("%lld%lld",&u,&v);
u^=ans;
v^=ans;
ans=ans1[]=ans1[]=ans2[]=ans2[]=;
int t=dep[v]-dep[work1(nowrt,u,v)]*;
ans=(ans+ans1[]*(t*+)%mod+ans2[]*t%mod*(t+)%mod)%mod;
ans=(ans-ans1[]*(dep[v]*+)%mod+ans2[]*dep[v]%mod*(dep[v]+)%mod+mod)%mod;
ans=(ans*)%(ll)mod;
ans=(ans+mod)%mod;
printf("%lld\n",ans);
}else{
scanf("%lld",&u);
u^=ans;
nowrt=u;
}
}
return ;
}

【xsy2440】【GDOI2016】疯狂动物城的更多相关文章

  1. 《疯狂动物城》主题曲《TryEverything》中文翻译

    <疯狂动物城>主题曲<TryEverything>夏奇拉激情献唱,很多事情是需要是试试,不试试就不知道可以成功. Oh oh oh oh oooh 哦哦哦哦哦 Oh oh oh ...

  2. [GDOI2016][树链剖分+主席树]疯狂动物城

    题面 Description Nick 是只在动物城以坑蒙拐骗为生的狐狸,儿时受到偏见的伤害,放弃了自己的理想.他被兔子 Judy 设下圈套,被迫与她合作查案,而卷入意想不到的阴谋,历尽艰险后成为搭档 ...

  3. COGS-2049 疯狂动物城

    Description 你意外来到了一个未知的星球, 这里是一个动物乌托邦, 生活着一群拥有非凡智力的动物. 你遇到了一个叫做尼克的狐狸, 他准备给他的 GF 过生日 . 他将制作一个巨大的多层蛋糕, ...

  4. 【GDOI 2016 Day1】疯狂动物城

    题目 分析 注意注意:码农题一道,打之前做好心理准备. 对于操作1.2,修改或查询x到y的路径,显然树链剖分. 对于操作2,我们将x到y的路径分为x到lca(x,y)和lca(x,y)到y两部分. 对 ...

  5. [GDOI2016] 疯狂动物园 [树链剖分+可持久化线段树]

    题面 太长了,而且解释的不清楚,我来给个简化版的题意: 给定一棵$n$个点的数,每个点有点权,你需要实现以下$m$个操作 操作1,把$x$到$y$的路径上的所有点的权值都加上$delta$,并且更新一 ...

  6. GDOI2016酱油记(补发)

    这篇酱油记是前年发在MCHacker一个叫code-hub的博客上的(已崩),现在来补发一下... GDOI2016扯淡(爆零记) 大家好,我是巨弱DCDCBigBig,在五一期间和一群神牛去考GDO ...

  7. 【IOS】将一组包含中文的数据按照#ABC...Z✿分组

    上一篇文章[IOS]模仿windowsphone列表索引控件YFMetroListBox里面 我们一步步的实现了WindowsPhone风格的索引. 但是有没有发现,如果你要实现按照字母排序,你还得自 ...

  8. 可变数组NSMutableArray

    //创建一个空的可变数组 NSMutableArray *array = [NSMutableArray array]; //向数组里面添加对象 [array addObject:@"< ...

  9. spring笔记--依赖注入之针对不同类型变量的几种注入方式

    控制反转和依赖注入讲的都是一个概念,只不过是站在了不同的角度,所谓的依赖注入: 是指在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bea ...

随机推荐

  1. UTC时间和各个地区的时间到底是怎么回事

    就不分析了,直接写结论 1.同一个时间点全球各地的时间戳是一致的 2.同一个时间戳在不同的时区对应不同的时间   依北京时间为例: 当前时间为 Tue Jan 23 2018 19:02:11 GMT ...

  2. JS实现HTML打印机效果

    5月最近在学Django,所以所有的Demo都没有PO出去 <!DOCTYPE html> <html lang="en"> <head> &l ...

  3. 多进程Socket_Server

    import socketserverclass MyServer(socketserver.BaseRequestHandler): def handle(self): #继承BaseRequest ...

  4. Python的流程控制

    条件判断 通过`if`,`elif`,`else`关键字来实现条件判断逻辑的实现,执行改结构中的其中一个,其结构如下: if condition1: pass elif condition2: pas ...

  5. kernel zram feature

    what is zram? Zram wiki zram zram(也称为 zRAM,先前称为 compcache)是 Linux 内核的一项功能,可提供虚拟内存压缩.zram 通过在 RAM 内的压 ...

  6. Python数学实现二元一次方程

    import cmath import math import sys def get_float(msg,allow_zero): x = None while x is None: try: x ...

  7. nginx配置修改

    改变nginx配置想让它生效而不停止服务,如下两种方式都可以:1) 检查nginx配置: nginx -t; 配置重载: nginx -s reload2) 检查nginx配置: nginx -t; ...

  8. BZOJ——1602: [Usaco2008 Oct]牧场行走 || 洛谷—— P2912 [USACO08OCT]牧场散步Pasture Walking

    http://www.lydsy.com/JudgeOnline/problem.php?id=1602 || https://www.luogu.org/problem/show?pid=2912 ...

  9. 【Android】桌面歌词悬浮效果简单实现

    在使用"网易云音乐"的时候,发现有一个显示"桌面歌词"的功能,于是就想着自己实现下.查了下资料,是用WindowManage实现的.实现过程中也出现了些问题,看 ...

  10. ACM这一路

    出自自己内心的声音.         大学已经读了一年,自己也老了一岁. 从開始的什么都不懂,到如今的懂了也不想多说什么,说多了也是累.在大学其中唯一还在执着的是ACM.这个也是我唯一能执着的东西,由 ...