【BZOJ3091】城市旅行

Description

Input

Output

Sample Input

4 5
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4

Sample Output

16/3
6/1

HINT

对于所有数据满足 1<=N<=50,000 1<=M<=50,000 1<=Ai<=10^6 1<=D<=100 1<=U,V<=N

题解:做过不少在线段树上推式子的,但是头一次做到将式子放到树上然后用splay进行区间合并的~

$ans=\sum v[i]*dep[i]*(dep[y]-dep[i]+1)=\sum v[i]*dep[i]*(dep[y]+1)-\sum v[i]*dep[i]*dep[i]$

所以我们只需要维护v[i]*dep[i]和v[i]*dep[i]*dep[i]即可。由于我们在查询时a和b会跑到同一个splay里,所以节点i的dep就是i在splay中的中序遍历序。然后用v[i]更新v[i]*dep[i],用v[i]和v[i]*dep[i]更新v[i]*dep[i]*dep[i]即可。

但是问题来了,翻转!翻转我们怎么办?翻转操作会使所有的dep全都改变,于是我们需要维护两套v[i],v[i]*dep,v[i]*dep*dep,一套是正的,一套是反的,翻转操作时我们只需要交换这两套即可。

此外,LCT的瓶颈依然在findroot操作那里,一开始TLE,改了改姿势就过了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=50010;
struct LCT
{
int ch[2],fa,rev;
ll v,ts,s0[2],s1[2],s2[2],siz;
}s[maxn];
int n,m;
bool isr(int x) {return s[s[x].fa].ch[0]!=x&&s[s[x].fa].ch[1]!=x;}
void add(int x,ll val)
{
s[x].v+=val,s[x].ts+=val;
s[x].s0[0]+=s[x].siz*val,s[x].s1[0]+=s[x].siz*(s[x].siz+1)/2*val,s[x].s2[0]+=s[x].siz*(s[x].siz+1)*(2*s[x].siz+1)/6*val;
s[x].s0[1]+=s[x].siz*val,s[x].s1[1]+=s[x].siz*(s[x].siz+1)/2*val,s[x].s2[1]+=s[x].siz*(s[x].siz+1)*(2*s[x].siz+1)/6*val;
}
void pushup(int x)
{
s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1;
s[x].s0[0]=s[s[x].ch[0]].s0[0]+s[s[x].ch[1]].s0[0]+s[x].v;
s[x].s1[0]=s[s[x].ch[0]].s1[0]+s[s[x].ch[1]].s1[0]+(s[s[x].ch[1]].s0[0]+s[x].v)*(s[s[x].ch[0]].siz+1);
s[x].s2[0]=s[s[x].ch[0]].s2[0]+s[s[x].ch[1]].s2[0]+(s[s[x].ch[1]].s0[0]+s[x].v)*(s[s[x].ch[0]].siz+1)*(s[s[x].ch[0]].siz+1)+2*s[s[x].ch[1]].s1[0]*(s[s[x].ch[0]].siz+1);
s[x].s0[1]=s[s[x].ch[1]].s0[1]+s[s[x].ch[0]].s0[1]+s[x].v;
s[x].s1[1]=s[s[x].ch[1]].s1[1]+s[s[x].ch[0]].s1[1]+(s[s[x].ch[0]].s0[1]+s[x].v)*(s[s[x].ch[1]].siz+1);
s[x].s2[1]=s[s[x].ch[1]].s2[1]+s[s[x].ch[0]].s2[1]+(s[s[x].ch[0]].s0[1]+s[x].v)*(s[s[x].ch[1]].siz+1)*(s[s[x].ch[1]].siz+1)+2*s[s[x].ch[0]].s1[1]*(s[s[x].ch[1]].siz+1);
}
void rever(int x)
{
s[x].rev^=1;
swap(s[x].ch[0],s[x].ch[1]);
swap(s[x].s0[0],s[x].s0[1]),swap(s[x].s1[0],s[x].s1[1]),swap(s[x].s2[0],s[x].s2[1]);
}
void pushdown(int x)
{
if(s[x].ts)
{
if(s[x].ch[0]) add(s[x].ch[0],s[x].ts);
if(s[x].ch[1]) add(s[x].ch[1],s[x].ts);
s[x].ts=0;
}
if(s[x].rev)
{
if(s[x].ch[0]) rever(s[x].ch[0]);
if(s[x].ch[1]) rever(s[x].ch[1]);
s[x].rev=0;
}
}
void updata(int x)
{
if(!isr(x)) updata(s[x].fa);
pushdown(x);
}
void rotate(int x)
{
int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
if(!isr(y)) s[z].ch[y==s[z].ch[1]]=x;
s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y;
s[x].ch[d^1]=y;
pushup(y),pushup(x);
}
void splay(int x)
{
updata(x);
while(!isr(x))
{
int y=s[x].fa,z=s[y].fa;
if(!isr(y))
{
if((x==s[y].ch[0])^(y==s[z].ch[0])) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
for(int y=0;x;splay(x),s[x].ch[1]=y,pushup(x),y=x,x=s[x].fa);
}
int findr(int x)
{
while(s[x].fa) x=s[x].fa;
return x;
}
void maker(int x)
{
access(x),splay(x),rever(x);
}
void link(int x,int y)
{
maker(x),access(y),splay(y),s[x].fa=y;
}
void cut(int x,int y)
{
maker(x),access(y),splay(y);
if(s[y].ch[0]==x&&!s[x].ch[1]) s[y].ch[0]=s[x].fa=0,pushup(y);
}
ll gcd(ll a,ll b)
{
return (!b)?a:gcd(b,a%b);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
//freopen("bz3091.in","r",stdin);
n=rd(),m=rd();
int i,a,b,c,d;
ll t1,t2,g;
for(i=1;i<=n;i++) s[i].v=rd(),pushup(i);
for(i=1;i<n;i++) a=rd(),b=rd(),link(a,b);
for(i=1;i<=m;i++)
{
d=rd(),a=rd(),b=rd();
if(d==1) cut(a,b);
if(d==2) if(findr(a)!=findr(b)) link(a,b);
if(d==3)
{
c=rd();
if(findr(a)==findr(b)) maker(a),access(b),splay(b),add(b,c);
}
if(d==4)
{
if(findr(a)!=findr(b)) printf("-1\n");
else
{
maker(a),access(b),splay(b),t1=(s[b].siz+1)*s[b].s1[0]-s[b].s2[0],t2=s[b].siz*(s[b].siz+1)/2,g=gcd(t1,t2);
printf("%lld/%lld\n",t1/g,t2/g);
}
}
}
return 0;
}

【BZOJ3091】城市旅行 LCT的更多相关文章

  1. BZOJ3091城市旅行——LCT区间信息合并

    题目描述 输入 输出 样例输入 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 样例输出 16/3 6/1 提示 对于所有数据满足 1& ...

  2. BZOJ3091 城市旅行 LCT

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3091 题意概括 鉴于本人语文不好,此题的描述原题很清晰,废话不多,请看原题. 可怕,原题是图片,不 ...

  3. bzoj3091 城市旅行 LCT + 区间合并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3091 题解 调了整个晚自习才调出来的问题. 乍一看是个 LCT 板子题. 再看一眼还是个 LC ...

  4. BZOJ3091: 城市旅行(LCT,数学期望)

    Description Input Output Sample Input 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 Sample ...

  5. 【LCT】BZOJ3091 城市旅行

    3091: 城市旅行 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1927  Solved: 631[Submit][Status][Discuss ...

  6. BZOJ 3091: 城市旅行 [LCT splay 期望]

    3091: 城市旅行 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1454  Solved: 483[Submit][Status][Discuss ...

  7. 【bzoj3091】城市旅行 LCT区间合并

    题目描述 输入 输出 样例输入 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 样例输出 16/3 6/1 题解 LCT区间合并 前三个 ...

  8. BZOJ 3091: 城市旅行 lct 期望 splay

    https://www.lydsy.com/JudgeOnline/problem.php?id=3091 https://blog.csdn.net/popoqqq/article/details/ ...

  9. bzoj 3091: 城市旅行 LCT

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3091 题解: 首先前三个操作就是裸的LCT模板 只考虑第四个操作. 要求我们计算期望,所以我 ...

随机推荐

  1. springBoot 快捷键

    设置idea导入包 勾选标注 2 选项,IntelliJ IDEA 将在我们书写代码的时候自动帮我们优化导入的包,比如自动去掉一些没有用到的包. 勾选标注 1 选项,IntelliJ IDEA 将在我 ...

  2. C# 键值对的类型

    一 C# 键值对类有以下类: ①    IDictionary<string, Object> idc = new Dictionary<string, object>(); ...

  3. 牛客网 牛客练习赛13 C.幸运数字Ⅲ-思维

    C.幸运数字Ⅲ   链接:https://www.nowcoder.com/acm/contest/70/C来源:牛客网     这个题447和477是特殊的,其他的就没什么了.   代码: 1 #i ...

  4. Mysql varchar长度问题

    http://dinglin.iteye.com/blog/914276 http://www.cnblogs.com/fakis/archive/2011/03/07/1976532.html   ...

  5. 构建更好的HashMap

    在7月份的那期 Java理论与实践(“并发集合类”)中,我们简单地回顾了可伸缩性的瓶颈,并讨论了怎么用共享数据结构的方法获得更高的并发性和吞吐量.有时候学习的最好方法是分析专家的成果,所以这个月我们将 ...

  6. vs2013 x64 编译汇编代码

    x64不再支持__asm, 只能单独放在一个.asm中. xxx.asm--------属性 应用    会出现 自定义生成工具.  下面黑体是我们修改的内容.

  7. angular使用canvas操作时报错

    最近,用 angular 前端框架为应用登录新增图形验证码认证,由于没有现成的插件,于是便使用canvas+js操作,也是可以正常使用,但是在编译阶段却有个报错: ERROR in src/app/l ...

  8. Java的日志模块

    目前主流的是是logback和log4j2,它们底层实现用的都是slf4j,通过slf4j-api调用 使用指定类初始化日志对象,在日志输出的时候,可以打印出日志信息所在类如:Logger logge ...

  9. circular-array-loop(蛮难的)

    https://leetcode.com/problems/circular-array-loop/ 题目蛮难的,有一些坑. 前后两个指针追赶找环的方法,基本可以归结为一种定式.可以多总结. pack ...

  10. 126. Word Ladder II(hard)

    126. Word Ladder II 题目 Given two words (beginWord and endWord), and a dictionary's word list, find a ...