【BZOJ3091】城市旅行 LCT
【BZOJ3091】城市旅行
Description
.jpg)
Input
.jpg)
Output
.jpg)
Sample Input
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
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的更多相关文章
- 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& ...
- BZOJ3091 城市旅行 LCT
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3091 题意概括 鉴于本人语文不好,此题的描述原题很清晰,废话不多,请看原题. 可怕,原题是图片,不 ...
- bzoj3091 城市旅行 LCT + 区间合并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3091 题解 调了整个晚自习才调出来的问题. 乍一看是个 LCT 板子题. 再看一眼还是个 LC ...
- 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 ...
- 【LCT】BZOJ3091 城市旅行
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1927 Solved: 631[Submit][Status][Discuss ...
- BZOJ 3091: 城市旅行 [LCT splay 期望]
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1454 Solved: 483[Submit][Status][Discuss ...
- 【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区间合并 前三个 ...
- BZOJ 3091: 城市旅行 lct 期望 splay
https://www.lydsy.com/JudgeOnline/problem.php?id=3091 https://blog.csdn.net/popoqqq/article/details/ ...
- bzoj 3091: 城市旅行 LCT
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3091 题解: 首先前三个操作就是裸的LCT模板 只考虑第四个操作. 要求我们计算期望,所以我 ...
随机推荐
- Eclipse 导入项目乱码问题
1.编码不对 a.对某文件或某工程更改编码: 鼠标移到工程名或文件名,右键->Properties->Resource->Text file enCoding ->更改编码(G ...
- HDU5877 Weak Pair
题目链接 Weak Pair 题意十分明确, 就是求出符合题意的有序点对个数. 首先对ai离散,离散之后的结果用rk[i]表示,然后进行二分预处理得到f[i],其中f[i]的意义为:其他的点和i这个节 ...
- BZOJ 3672 NOI 2014 购票
题面 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市 ...
- HNOI 2006 BZOJ 1195 最短母串
题面 问题描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字 ...
- Flexible and Economical UTF-8 Decoder
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
- 聊聊、Zookeeper Windows启动
Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly rel ...
- Learn How To Create Trigger In Oracle Forms
I have written many posts related to triggers in Oracle Forms, I have given examples for Form Level ...
- 2016.10.10 Failed to start component [StandardService[Catalina]]
Failed to start component [StandardService[Catalina]] 错误原因:有数据残留,点击clean(见下图) 解决办法: 右键点击servers下 ...
- zookeeper客户端 和服务器连接时版本问题
在使用kafka 和zookeeper 实现实时分析程序时,由于zookeeper部署版本和分析程序导入jar包的版本不一致,导致了当实时分析程序从远程服务器连接kafka集群的zookeeper时报 ...
- java类中,成员变量赋值第一个进行,其次是静态构造函数,再次是构造函数
如题是结论,如果有人问你Java类的成员初始化顺序和初始化块知识就这样回答他.下面是代码: package com.test; public class TestClass{ // 成员变量赋值第一个 ...