BZOJ 3091: 城市旅行 [LCT splay 期望]
3091: 城市旅行
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1454 Solved: 483
[Submit][Status][Discuss]
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
Source
谜一般的翻转标记
大爷题解传送门:http://blog.csdn.net/popoqqq/article/details/40823659
与上一题不一样的是,每个点在链上的位置不一定,所以没法维护vi*i之类的东西,只能像那样记录lsum和rsum然后update的时候处理
本题的翻转标记必须立即生效,因为反转标记还会影响lsum和rsum
除了一开始就Link外,还可以保存图然后dfs只设置fa关系不用Link,然而并没有带来常数提升反而更慢了...
BZOJ 100题达成
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define pa t[x].fa
#define lc t[x].ch[0]
#define rc t[x].ch[1]
const int N=5e4+;
typedef long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} struct node{
int ch[],fa,rev;
ll add,lsum,rsum,sum,exp,w,size;
}t[N];
inline int wh(int x){return t[pa].ch[]==x;}
inline int isRoot(int x){return t[pa].ch[]!=x&&t[pa].ch[]!=x;}
inline void update(int x){
t[x].size=t[lc].size+t[rc].size+;
t[x].sum=t[lc].sum+t[rc].sum+t[x].w;
t[x].lsum=t[lc].lsum+t[x].w*(t[lc].size+)+t[rc].lsum+t[rc].sum*(t[lc].size+);
t[x].rsum=t[rc].rsum+t[x].w*(t[rc].size+)+t[lc].rsum+t[lc].sum*(t[rc].size+);
t[x].exp=t[lc].exp+t[rc].exp
+t[lc].lsum*(t[rc].size+)+t[rc].rsum*(t[lc].size+)
+t[x].w*(t[lc].size+)*(t[rc].size+);
}
inline ll cal1(ll x){return x*(x+)/;}
inline ll cal2(ll x){return x*(x+)*(x+)/;}
inline void paint(int x,ll d){
t[x].w+=d;
t[x].add+=d;
t[x].sum+=d*t[x].size;
t[x].lsum+=d*cal1(t[x].size);
t[x].rsum+=d*cal1(t[x].size);
t[x].exp+=d*cal2(t[x].size);
}
inline void rever(int x){
swap(lc,rc);
swap(t[x].lsum,t[x].rsum);
t[x].rev^=;
}
inline void pushDown(int x){
if(t[x].rev){
rever(lc);
rever(rc);//!!!!!
t[x].rev=;
}
if(t[x].add){
paint(lc,t[x].add);
paint(rc,t[x].add);
t[x].add=;
}
} inline void rotate(int x){
int f=t[x].fa,g=t[f].fa,c=wh(x);
if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
t[f].ch[c]=t[x].ch[c^];t[t[f].ch[c]].fa=f;
t[x].ch[c^]=f;t[f].fa=x;
update(f);update(x);
}
int st[N],top;
inline void splay(int x){
top=;st[++top]=x;
for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
for(int i=top;i>=;i--) pushDown(st[i]); for(;!isRoot(x);rotate(x))
if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
} inline void Access(int x){
for(int y=;x;y=x,x=pa){
splay(x);
rc=y;
update(x);
}
}
inline void MakeR(int x){
Access(x);splay(x);
rever(x);
}
inline int FindR(int x){
Access(x);splay(x);
while(lc) x=lc;
return x;
}
inline void Link(int x,int y){
MakeR(x);
t[x].fa=y;
}
inline void Cut(int x,int y){
MakeR(x);Access(y);splay(y);
t[y].ch[]=t[x].fa=;
update(y);//!!!
}
inline void Add(int x,int y,int d){
if(FindR(x)!=FindR(y)) return;
MakeR(x);Access(y);splay(y);
paint(y,d);
}
inline ll gcd(ll a,ll b){return b==?a:gcd(b,a%b);}
inline void Que(int x,int y){
if(FindR(x)!=FindR(y)){puts("-1");return;}
MakeR(x);Access(y);splay(y);
ll a=t[y].exp,b=t[y].size*(t[y].size+)/;
ll g=gcd(a,b);//printf("Que %d %d %d\n",a,b,g);
printf("%lld/%lld\n",a/g,b/g);
}
int n,Q,a,op,x,y,d;
int main(){
n=read();Q=read();
for(int i=;i<=n;i++){
a=read();
t[i].size=;
t[i].w=t[i].lsum=t[i].rsum=t[i].sum=t[i].exp=a;
}
for(int i=;i<=n-;i++) x=read(),y=read(),Link(x,y);
while(Q--){
op=read();x=read();y=read();
if(op==) if(FindR(x)==FindR(y)) Cut(x,y);
if(op==) if(FindR(x)!=FindR(y)) Link(x,y);
if(op==) d=read(),Add(x,y,d);
if(op==) Que(x,y);
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define pa t[x].fa
#define lc t[x].ch[0]
#define rc t[x].ch[1]
const int N=5e4+;
typedef long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} struct node{
int ch[],fa,rev;
ll add,lsum,rsum,sum,exp,w,size;
}t[N];
inline int wh(int x){return t[pa].ch[]==x;}
inline int isRoot(int x){return t[pa].ch[]!=x&&t[pa].ch[]!=x;}
inline void update(int x){
t[x].size=t[lc].size+t[rc].size+;
t[x].sum=t[lc].sum+t[rc].sum+t[x].w;
t[x].lsum=t[lc].lsum+t[x].w*(t[lc].size+)+t[rc].lsum+t[rc].sum*(t[lc].size+);
t[x].rsum=t[rc].rsum+t[x].w*(t[rc].size+)+t[lc].rsum+t[lc].sum*(t[rc].size+);
t[x].exp=t[lc].exp+t[rc].exp
+t[lc].lsum*(t[rc].size+)+t[rc].rsum*(t[lc].size+)
+t[x].w*(t[lc].size+)*(t[rc].size+);
}
inline ll cal1(ll x){return x*(x+)/;}
inline ll cal2(ll x){return x*(x+)*(x+)/;}
inline void paint(int x,ll d){
t[x].w+=d;
t[x].add+=d;
t[x].sum+=d*t[x].size;
t[x].lsum+=d*cal1(t[x].size);
t[x].rsum+=d*cal1(t[x].size);
t[x].exp+=d*cal2(t[x].size);
}
inline void rever(int x){
swap(lc,rc);
swap(t[x].lsum,t[x].rsum);
t[x].rev^=;
}
inline void pushDown(int x){
if(t[x].rev){
rever(lc);
rever(rc);//!!!!!
t[x].rev=;
}
if(t[x].add){
paint(lc,t[x].add);
paint(rc,t[x].add);
t[x].add=;
}
} inline void rotate(int x){
int f=t[x].fa,g=t[f].fa,c=wh(x);
if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
t[f].ch[c]=t[x].ch[c^];t[t[f].ch[c]].fa=f;
t[x].ch[c^]=f;t[f].fa=x;
update(f);update(x);
}
int st[N],top;
inline void splay(int x){
top=;st[++top]=x;
for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
for(int i=top;i>=;i--) pushDown(st[i]); for(;!isRoot(x);rotate(x))
if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
} inline void Access(int x){
for(int y=;x;y=x,x=pa){
splay(x);
rc=y;
update(x);
}
}
inline void MakeR(int x){
Access(x);splay(x);
rever(x);
}
inline int FindR(int x){
Access(x);splay(x);
while(lc) x=lc;
return x;
}
inline void Link(int x,int y){
MakeR(x);
t[x].fa=y;
}
inline void Cut(int x,int y){
MakeR(x);Access(y);splay(y);
t[y].ch[]=t[x].fa=;
update(y);//!!!
}
inline void Add(int x,int y,int d){
if(FindR(x)!=FindR(y)) return;
MakeR(x);Access(y);splay(y);
paint(y,d);
}
inline ll gcd(ll a,ll b){return b==?a:gcd(b,a%b);}
inline void Que(int x,int y){
if(FindR(x)!=FindR(y)){puts("-1");return;}
MakeR(x);Access(y);splay(y);
ll a=t[y].exp,b=t[y].size*(t[y].size+)/;
ll g=gcd(a,b);//printf("Que %d %d %d\n",a,b,g);
printf("%lld/%lld\n",a/g,b/g);
}
int n,Q,a,op,x,y,d; struct edge{
int v,ne;
}e[N<<];
int cnt,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
inline void dfs(int u,int fa){
for(int i=h[u];i;i=e[i].ne)
if(e[i].v!=fa){
t[e[i].v].fa=u;
dfs(e[i].v,u);
}
}
int main(){
n=read();Q=read();
for(int i=;i<=n;i++){
a=read();
t[i].size=;
t[i].w=t[i].lsum=t[i].rsum=t[i].sum=t[i].exp=a;
}
for(int i=;i<=n-;i++) x=read(),y=read(),ins(x,y);
dfs(,);
while(Q--){
op=read();x=read();y=read();
if(op==) if(FindR(x)==FindR(y)) Cut(x,y);
if(op==) if(FindR(x)!=FindR(y)) Link(x,y);
if(op==) d=read(),Add(x,y,d);
if(op==) Que(x,y);
}
}
BZOJ 3091: 城市旅行 [LCT splay 期望]的更多相关文章
- 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模板 只考虑第四个操作. 要求我们计算期望,所以我 ...
- bzoj 3091 城市旅行(LCT+数学分析)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3091 [思路] 膜Popoqqq大爷的题解 click here [代码]是坑... ...
- BZOJ 3091 城市旅行
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 ...
- 【BZOJ3091】城市旅行 LCT
[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 ...
- 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 ...
- 【BZOJ】3091: 城市旅行 Link-Cut Tree
[题意]参考PoPoQQQ. 给定一棵树,每个点有一个点权,提供四种操作: 1.删除两点之间的连边 不存在边则无视 2.在两点之前连接一条边 两点已经联通则无视 3.在两点之间的路径上所有点的点权加上 ...
- bzoj3091 城市旅行 LCT + 区间合并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3091 题解 调了整个晚自习才调出来的问题. 乍一看是个 LCT 板子题. 再看一眼还是个 LC ...
- 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& ...
随机推荐
- 总结过滤器,监听器,servlet的异同点,已经执行顺序。
1.过滤器 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml ...
- C语言函数的作用域规则
“语言的作用域规则”是一组确定一部分代码是否“可见”或可访问另一部分代码和数据的规则. “同一函数中,不同的结构体成员名能相同,当变量处于不同的作用域时,名称可以相同. 注:作用域,其对象是变量, ...
- sass 安装与使用
1.安装. 安装ruby :http://rubyinstaller.org/downloads 创建项目:在f盘创建一个名为sass的文件夹 ruby命令行:f: ruby命令行:cd sass r ...
- sublime汉化教程
转自: http://www.cnblogs.com/marsggbo/p/6622960.html 如何给sublime text3安装汉化包?so easy 哦 这是我本人亲身测试过的,肯定有效, ...
- [国嵌攻略][060][LCD工作原理解析]
LCD硬件体系 1.LCD液晶屏 液晶属于一种有机化合物,分子形状为长棒状,在不同的电流作用下,分子会有规律旋转,这样对光线产生一定的控制形成一个像素,而很多像素右可以构成完整的图像. LCD是Liq ...
- [国嵌攻略][045-046][一跃进入C大门]
[一跃进入C大门] 跳转方式 1.相对跳转:b或bl指令,通过计算两个地址之间的差值来给pc赋值相对跳转 2.绝对跳转:ldr指令,通过给pc直接赋值,完成绝对跳转 代码编写 1.在汇编代码中直接使用 ...
- SpringBoot介绍及环境搭建
什么是SpringBoot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不 ...
- 如何初始化grunt
为什么使用任务运行工具Grunt -- 官方解释 简而言之,自动化.当你处理诸如代码最小化, 代码编译, 单元测试, 代码规范校验等等重复任务时, 你必须要做的工作越少,你的工作就变得越简单.在你完成 ...
- Hive_UDF函数中集合对象初始化的注意事项
UDF函数中定义的集合对象何时初始化 udf函数放在sql中对某个字段进行处理,那么在底层会创建一个该类的对象,这个对象不断的去调用这个evaluate(...)方法,截图如下: 1.1 如果说对 ...
- Cookie实现--用户上次访问时间
用户上次访问时间