【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模板 只考虑第四个操作. 要求我们计算期望,所以我 ...
随机推荐
- PHP如何在页面中原样输出HTML代码
字符串与HTML之间的相互转换主要应用htmlentities()函数来完成. header("Content-Type: text/html; charset=utf-8"); ...
- C#规范整理·泛型委托事件
基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用.同时,它减少了泛型类及泛型方法中的转型,确保了类型安全.委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊,它是 ...
- DotnetBrowser入门教程-(2)启动简单的Web服务
微软的网页服务向来与IIS捆绑紧密,虽然.net core可以脱离iis了,但是基于国内的xp系统,.net core类库的精简,使得我们仍然在dotnetbrowser增加了对web服务的支持. 先 ...
- 海量数据插入数据库效率对照測试 ---ADO.NET下SqlBulkCopy()对照LINQ 下InsertAllOnSubmit()
摘要:使用.NET相关技术向数据库中插入海量数据是经常使用操作.本文对照ADO.NET和LINQ两种技术.分别使用SqlBulkCopy()和InsertAllOnSubmit()方法进行操作. 得出 ...
- JAVA基础针对自己薄弱环节总结01(循环之前的知识)
java中的标识符 组成:数字.字母.下划线.美元$符号组成. 规则:不能由数字开头. 类名:每一个单词的首字母大写 包名:所有小写 变量名.方法名:第一个单词首字母小写.后面首字母大写 常 ...
- Python 第三方 http 库-Requests 学习
Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...
- RPi Cam v2 之一:基础及牛刀小试
前言 原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正. 本文使用markdown写成,为获得更好的阅读体验,可以访问我的博客. 1.unboxing & comparison 包 ...
- vs 已经加入了引用,编译还是提示没有加入引用
已经加入了引用,可是.编译还是通只是. 原因:项目总体框架是.Net FramWork4.5,nep中的框架也是4.5.而编译只是的project是4.0. 解决的方法:将编译只是的项目框架改为4.5
- 【Python】随机漫步
创建Randomwalk()类 我们将使用Python来生成随机漫步数据,再使用matplotlib以引入瞩目的方式将这些数据呈现出来 首先创建类Randomwalk() from random im ...
- asp.net模拟请求
在asp.net模拟请求,微软在控件状态有安全性控制. __VIEWSTATE.__EVENTVALIDATION要与服务端页面(.aspx)中元素信息保存一致.