BZOJ 3091 城市旅行
Description
Input
Output
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
维护方法我就不再赘述了,见我博客的 BZOJ 2572 高速公路。这一题和那一题的维护方法其实是一样的,但是数据结构不同,很明显这是lct嘛。
但是那么问题就来,树上的序号id不是一定的,不像线段树一样,怎么办呢???
这就是本题的难点——维护id。但是细细想想其实也不是很难。
你想,他是要维护一条链上深度的id,左子树id<右子树,其实我们就是在access操作中对某一条链的id整体加上一个值或者减去一个值,这样来操作(splay维护的都是一条链)。因此,维护id就不成问题。
但是你有没有考虑过这样一种情况:根翻转了,他所在splay的id也全部都要翻转,这怎么办?其实也不难,将其所在splay中所有id都取负,再加上splay的size+1即可。
代码实现有许多的细节要处理:比如初始化连边,他貌似卡了你的link,如果你直接连的话,正确的做法是dfs直接将father连上去(这就是我开始tle了八九发的原因)。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std; typedef long long ll;
#define maxn 50010
int n,m,ch[maxn][],size[maxn],fa[maxn],stack[maxn];
int side[maxn],next[maxn*],toit[maxn*],cnt;
ll key[maxn],id[maxn],s1[maxn],s2[maxn],s3[maxn];
ll lef[maxn],rig[maxn],sign1[maxn],sign2[maxn];
bool rev[maxn]; inline int getint()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} inline ll getlong()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} inline ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; } inline void pushdown(int x)
{
int lc = ch[x][],rc = ch[x][];
if (rev[x])
{
id[x] = -id[x]; s2[x] = -s2[x];
swap(lef[x],rig[x]);
lef[x] = -lef[x]; rig[x] = -rig[x];
swap(ch[x][],ch[x][]);
if (lc) rev[lc] ^= ,sign2[lc] = -sign2[lc];
if (rc) rev[rc] ^= ,sign2[rc] = -sign2[rc];
rev[x] = false;
}
if (sign2[x])
{
lef[x] += sign2[x]; rig[x] += sign2[x]; id[x] += sign2[x];
s3[x] += (sign2[x]*s2[x]<<)+sign2[x]*sign2[x]*s1[x];
s2[x] += sign2[x]*s1[x];
if (lc) sign2[lc] += sign2[x];
if (rc) sign2[rc] += sign2[x];
sign2[x] = ;
}
if (sign1[x])
{
s1[x] += sign1[x]*(ll)size[x];
s2[x] += (ll)size[x]*(lef[x]+rig[x])/*sign1[x];
s3[x] += (rig[x]*(rig[x]+)*((rig[x]<<)+)/-(lef[x]-)*lef[x]*((lef[x]<<)-)/)*sign1[x];
key[x] += sign1[x];
if (lc) sign1[lc] += sign1[x];
if (rc) sign1[rc] += sign1[x];
sign1[x] = ;
}
} inline void updata(int x)
{
int lc = ch[x][],rc = ch[x][];
if (lc) pushdown(lc); if (rc) pushdown(rc);
size[x] = size[lc]+size[rc]+;
s1[x] = s1[lc]+s1[rc]+key[x];
s2[x] = id[x]*key[x]+s2[lc]+s2[rc];
s3[x] = id[x]*id[x]*key[x]+s3[lc]+s3[rc];
lef[x] = rig[x] = id[x];
if (lc) lef[x] = lef[lc];
if (rc) rig[x] = rig[rc];
} inline bool isroot(int a) { return ch[fa[a]][] != a&&ch[fa[a]][] != a; } inline void rotate(int x)
{
int y = fa[x],z = fa[y],l = ch[y][]==x,r = l^;
if (!isroot(y)) ch[z][ch[z][]==y] = x; fa[x] = z;
if (ch[x][r]) fa[ch[x][r]] = y; ch[y][l] = ch[x][r];
ch[x][r] = y; fa[y] = x;
updata(y); updata(x);
} inline void splay(int x)
{
int top = ,i;
for (i = x;!isroot(i);i = fa[i]) stack[++top] = i;
stack[++top] = i;
while (top) pushdown(stack[top--]);
while (!isroot(x))
{
int y = fa[x],z = fa[y];
if (!isroot(y))
{
if ((ch[y][]==x)^(ch[z][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
} inline int access(int x)
{
int t;
for (t = ;x;t = x,x = fa[x])
{
splay(x);
if (ch[x][]) sign2[ch[x][]] -= size[ch[x][]]+;
ch[x][] = t;
if (t) sign2[t] += size[ch[x][]]+;
updata(x);
}
return t;
} inline void evert(int x)
{
x = access(x); rev[x] ^= ;
sign2[x] += rev[x]*(size[x]+);
} inline int find(int x)
{
x = access(x);
while (pushdown(x),ch[x][]) x = ch[x][];
return x;
} inline void cut(int x,int y)
{
evert(x); access(y); splay(y);
if (ch[y][] != x||ch[x][] != ) return;
ch[y][] = fa[x] = ;
updata(x);
sign2[y] -= size[x];
} inline void link(int x,int y)
{
if (find(x) == find(y)) return;
evert(x); fa[x] = y;
} inline void change(int x,int y,ll v)
{
if (find(x) != find(y)) return;
evert(x); x = access(y);
sign1[x] += v;
pushdown(x);
} inline void ask(int x,int y)
{
if (find(x) != find(y)) { printf("-1\n"); return; }
evert(x); access(y); splay(x);
ll up = -s3[x]+(ll)(size[x]+)*s2[x],down = (ll)size[x]*(ll)(size[x]+)>>,d = gcd(up,down);
up /= d; down /= d;
printf("%lld/%lld\n",up,down);
} inline void add(int a,int b) { next[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b; } inline void ins(int a,int b) { add(a,b); add(b,a); } inline void dfs(int now,int f)
{
if (f) fa[now] = f;
for (int i = side[now];i;i = next[i])
if (toit[i] != f) dfs(toit[i],now);
} int main()
{
freopen("3091.in","r",stdin);
freopen("3091.out","w",stdout);
scanf("%d %d",&n,&m);
for (int i = ;i <= n;++i)
{
key[i] = getlong();
s1[i] = s2[i] = s3[i] = key[i];
size[i] = lef[i] = rig[i] = id[i] = ;
}
for (int i = ;i < n;++i)
{
int a = getint(),b = getint();
ins(a,b);
}
dfs(,);
while (m--)
{
int opt = getint();
if (opt == )
{
int u = getint(),v = getint(); ll d = getlong();
change(u,v,d);
}
else
{
int u = getint(),v = getint();
if (opt == ) cut(u,v);
else if (opt == ) link(u,v);
else ask(u,v);
}
}
fclose(stdin); fclose(stdout);
return ;
}
BZOJ 3091 城市旅行的更多相关文章
- BZOJ 3091: 城市旅行 [LCT splay 期望]
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1454 Solved: 483[Submit][Status][Discuss ...
- bzoj 3091 城市旅行(LCT+数学分析)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3091 [思路] 膜Popoqqq大爷的题解 click here [代码]是坑... ...
- 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: 城市旅行 Link-Cut Tree
[题意]参考PoPoQQQ. 给定一棵树,每个点有一个点权,提供四种操作: 1.删除两点之间的连边 不存在边则无视 2.在两点之前连接一条边 两点已经联通则无视 3.在两点之间的路径上所有点的点权加上 ...
- 【LCT】BZOJ3091 城市旅行
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1927 Solved: 631[Submit][Status][Discuss ...
- luogu P4842 城市旅行
嘟嘟嘟 好题,好题 刚开始突发奇想写了一个\(O(n ^ 2)\)暴力,结果竟然过了?!后来才知道是上传题的人把单个数据点开成了10s-- 不过不得不说我这暴力写的挺好看的.删边模仿链表删边,加边的时 ...
- 【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 ...
- (RERERERERERERERERERERE) BZOJ 2746: [HEOI2012]旅行问题
二次联通门 : BZOJ 2746: [HEOI2012]旅行问题 神TM STL的vector push_back进一个数后取出时就变成了一个很小的负数.. 调不出来了, 不调了 #include ...
随机推荐
- [TypeScript] Understanding Generics with RxJS
Libraries such as RxJS use generics heavily in their definition files to describe how types flow thr ...
- [RxJS] Transformation operators: delay and delayWhen
This lessons teaches about delay and delayWhen: simple operators that time shift. delay(number | dat ...
- 构造Nginx避免直接使用IP通路Webserver
他看上去非常Nginx构造,似乎忽略了ip直接访问Web问题,从理论上讲,这是不利于SEO优化,因此,我们希望能够避免直接使用IP访问该网站,但域名.详细介绍了如何做到这一点,看看下面的. 在官方文件 ...
- 【POJ3182】The Grove BFS 最短路径周围
意甲冠军:给定一个N*M图.,间'X'代表树木(树木必须汇集到森林,非分离),然后,'.'它代表的空间.'*'它代表的起点.现在它需要从起点.一圈,最后回到起点,所经过最少点数. 题目中给的'+'就是 ...
- eclipse 常见问题及解决
1. Target runtime Apache Tomcat v6.0 is not defined.错误解决方法 原文:http://blog.csdn.net/xw13106209/articl ...
- heap堆内存不足
配置jvm内存,加个启动参数 -Xms512m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256m start 下面是这个: -Dcatalina.h ...
- iOS 使用Charts框架 折线,柱状,K线,饼状,雷达全攻略
我是前言: 大约几个月前我在某平台写了一篇文章, 文中简单地介绍了Charts两种图表的样式的使用, 不过有种意犹未尽的感觉, 利用周末的空闲时间再次看了看, 有了新的收获, 今天发出来,分享给大家, ...
- Android开发:最详细的 NavigationDrawer 开发实践总结
最详细的 NavigationDrawer 开发实践总结 继前面写的两篇文章之后(有问题欢迎反馈哦): Android开发:Translucent System Bar 的最佳实践 Android开发 ...
- Java基础知识强化之集合框架笔记35:List练习之产生10个1~20之间的随机数(要求:随机数不能重复)
1. 需求:获取10个1-20之间的随机数,要求不能重复 用数组实现,但是数组的长度是固定的,长度不好确定.所以我们使用集合实现. 分析: • 创建产生随机数的对象 • 创建一个存储随机数的集合. • ...
- Android 布局
转自:http://www.cnblogs.com/chiao/archive/2011/08/24/2152435.html Android布局是应用界面开发的重要一环,在Android中,共有五种 ...