【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. EventBus 3.0: 入门使用及其使用 完全解析

    前言 EventBus是greenrobot再Android平台发布的以订阅-发布模式为核心的开源库. EventBus翻译过来是事件总线意思.可以这样理解:一个个(event)发送到总线上, 然后E ...

  2. ZOJ 3593.One Person Game-扩展欧几里得(exgcd)

    智障了,智障了,水一水博客. 本来是个水题,但是for循环遍历那里写挫了... One Person Game Time Limit: 2 Seconds      Memory Limit: 655 ...

  3. 关联分析(Apriori算法)

    两个概念: 频繁项集:常出现的物品集合 关联分析:找到诸如:尿布-->啤酒的关联,反过来则是另一条 两个控制参数: 项集的支持度(support):一个项集出现的次数在所有样本中出现的比例 可信 ...

  4. ECNU 3480 没用的函数 (ST表预处理 + GCD性质)

    题目链接  ECNU 2018 JAN Problem E 这题卡了双$log$的做法 令$gcd(a_{i}, a_{i+1}, a_{i+2}, ..., a_{j}) = calc(i, j)$ ...

  5. Maven在[INFO] Generating project in Interactive mode卡住的问题解决

    我的环境: Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00) Maven ...

  6. php设置报错级别

    ini_set("display_errors", "On");//若页面不报错的话,请设置php.ini 的display_errors 为 On error ...

  7. concurrencyProgrammingGuide 1

    thread用来表述执行代码的独立path.os x的线程执行基于POSIX 线程API. process用来表述一个运行操作,可以包含多个线程. task用来描述工作的抽象概念. Concurren ...

  8. 报错:LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 1>

    这段时间忙于看文献,没用过VS了. 今天用着用着就报错了: LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 1> 问度娘,大神给出了解决方法 ...

  9. EasyMvc入门教程-基本控件说明(1)按钮

    按钮是我们最常用的控件之一了,先看下我们提供的按钮风格: 不同颜色的: 实现代码: @Html.Q().Button().Text("Danger").ColorDanger() ...

  10. 2016.10.17 yaml文件里的labels和Pod、RC、Service的对应关系

    在看kubernetes的例子时,出现了一个疑问. Pod.RC.Service的yaml文件里,都出现了labels,还有labelSelector.有些不太清楚,因此就这点来学习下.   接上文: ...