bzoj 3091: 城市旅行 LCT
题目:
题解:
首先前三个操作就是裸的LCT模板
只考虑第四个操作.
要求我们计算期望,所以我们考虑计算出所有情况的和然后在除以情况的数目.
这样我们就找到分子分母了.
我们很容易发现分母即为\(\frac{n*(n+1)}{2}\)
对应到我们的Splay树上即\(\frac{siz*(siz+1)}{2}\)
所以我们现在考虑维护分子:
对于首先我们考虑在一个长为n的序列上统计这些东西
我们知道总和即为每一项乘以这一项出现的次数(又在废话)
出现的次数又是多少呢?
a_1 & a_2 & a_3 & ... & a_i &... & a_n \\
1*n & 2*(n-1) & 3*(n-2) & ...&i*(n-i+1) & ...& n*1 \\
\end{matrix}
\]
所以其实对于每一个元素,出现的次数都是\((\text{左边的}siz+1)*(\text{右边的}siz+1)\)
那么我们考虑合并:
假设这个区间作为合并的左区间,我们设\(w = \text{右区间的}siz+1\)(即这个区间合并后右侧新出现的节点数)
那么按照刚才的思路,所有的数字的后一项都会同时增大即变为:
a_1 & a_2 & a_3 & ... & a_i &... & a_n \\
1*(n+w) & 2*(n-1+w) & 3*(n-2+w) & ...&i*(n-i+1+w) & ...& n*(1+w) \\
\end{matrix}
\]
于是我们发现实际上这段区间的贡献增加了:
a_1 & a_2 & a_3 & ... & a_i &... & a_n \\
1*w & 2*w & 3*w & ...& i*w & ...& n*w \\
\end{matrix}
\]
所以我们记录一个和表示\(1*a_1 + 2*a_2 + 3*a_3 + ... + n*a_n\)即可
利用这个我们就可以维护分子了。啥?? 怎么维护 ??
\(val = ch[0]->val + ch[1]->val + ch[0]->lsum*(ch[1]->siz + 1) + ch[1]->rsum*(ch[0]->siz + 1) + w*(ch[0]->siz + 1)*(ch[1]->siz + 1);\)
其中\(w\)为节点本身的权,\(lsum = \sum_{i=1}^{n}a_i*i\),\(rsum = \sum_{i=1}^{n}a_i*(n-i+1)\)
至于维护\(lsum\)和\(rsum\)的过程.
我们有
\]
据说是小学数学难度.
夭折啊 !我想不出来 !
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
inline void read(ll &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const ll maxn = 50010;
struct Node{
Node *ch[2],*fa;
ll w,lsum,rsum,lazy;
ll val,siz,tag,sum;
void update();
void pushdown();
void rev();
void inc(ll x);
}*null;
void Node::rev(){
if(this == null) return;
swap(lsum,rsum);swap(ch[0],ch[1]);
tag ^= 1;
}
void Node::inc(ll x){
if(this == null) return;
w += x;sum += x*siz;
lsum += x*siz*(siz+1)/2;
rsum += x*siz*(siz+1)/2;
val += x*siz*(siz+1)*(siz+2)/6;
lazy += x;
}
void Node::pushdown(){
if(this == null) return;
if(lazy){
if(ch[0] != null) ch[0]->inc(lazy);
if(ch[1] != null) ch[1]->inc(lazy);
lazy = 0;
}
if(tag){
if(ch[0] != null) ch[0]->rev();
if(ch[1] != null) ch[1]->rev();
tag = 0;
}
}
void Node::update(){
if(this == null) return;
siz = ch[0]->siz + ch[1]->siz + 1;
sum = ch[0]->sum + ch[1]->sum + w;
lsum = ch[0]->lsum + w*(ch[0]->siz + 1) + ch[1]->lsum + ch[1]->sum*(ch[0]->siz + 1);
rsum = ch[1]->rsum + w*(ch[1]->siz + 1) + ch[0]->rsum + ch[0]->sum*(ch[1]->siz + 1);
val = ch[0]->val + ch[1]->val + ch[0]->lsum*(ch[1]->siz + 1) + ch[1]->rsum*(ch[0]->siz + 1) + w*(ch[0]->siz + 1)*(ch[1]->siz + 1);
}
Node mem[maxn],*it;
inline void init(){
it = mem;null = it++;
null->ch[0] = null->ch[1] = null->fa = null;
null->w = null->lsum = null->rsum = null->sum =
null->val = null->siz = null->tag = 0;
}
inline Node* newNode(ll x){
Node *p = it++;p->ch[0] = p->ch[1] = p->fa = null;
p->w = p->val = p->lsum = p->rsum = p->sum = x;p->siz = 1;
p->tag = p->lazy = 0;
return p;
}
inline void rotate(Node *p,Node *x){
ll k = p == x->ch[1];
Node *y = p->ch[k^1],*z = x->fa;
if(z->ch[0] == x) z->ch[0] = p;
if(z->ch[1] == x) z->ch[1] = p;
if(y != null) y->fa = x;
p->fa = z;p->ch[k^1] = x;
x->fa = p;x->ch[k] = y;
x->update();p->update();
}
inline bool isRoot(Node *p){
return (p == null) || (p->fa->ch[0] != p && p->fa->ch[1] != p);
}
inline void Splay(Node *p){
p->pushdown();
while(!isRoot(p)){
Node *x = p->fa,*y = x->fa;
y->pushdown();x->pushdown();p->pushdown();
if(isRoot(x)) rotate(p,x);
else if((p == x->ch[0])^(x == y->ch[0])) rotate(p,x),rotate(p,y);
else rotate(x,y),rotate(p,x);
}p->update();
}
inline Node* Access(Node *x){
for(Node *y = null;x != null;y = x,x = x->fa)
Splay(x),x->ch[1] = y,x->update();
return x;
}
inline void makeRoot(Node *x){
Access(x);Splay(x);x->rev();
}
inline void link(Node *x,Node *y){
makeRoot(x);x->fa = y;
}
inline void cut(Node *x,Node *y){
makeRoot(x);Access(y);Splay(y);
if(y->ch[0] == x && x->ch[1] == null){
y->ch[0] = y->ch[0]->fa = null;
y->update();
}
}
inline void inc(Node *x,Node *y,ll w){
makeRoot(x);Access(y);Splay(y);
y->inc(w);
}
inline ll gcd(const ll &a,const ll &b){return b == 0 ? a : gcd(b,a%b);}
inline ll query(Node *x,Node *y){
makeRoot(x);Access(y);Splay(y);
ll upside = y->val;
ll dnside = y->siz*(y->siz + 1)/2;
ll g = gcd(upside,dnside);
printf("%llu/%llu\n",upside/g,dnside/g);
}
inline Node* findRoot(Node *x){
Access(x);Splay(x);
while(x->ch[0] != null) x = x->ch[0];
Splay(x);return x;
}
int main(){
init();
ll n,m;read(n);read(m);
for(ll i=1,x;i<=n;++i){
read(x);newNode(x);
}
ll u,v;
for(ll i=1;i<n;++i){
read(u);read(v);
link(mem+u,mem+v);
}
ll op;
while(m--){
read(op);
if(op == 1){
read(u);read(v);
if(u != v && findRoot(mem+u) == findRoot(mem+v)) cut(mem+u,mem+v);
}else if(op == 2){
read(u);read(v);
if(findRoot(mem+u) != findRoot(mem+v)) link(mem+u,mem+v);
}else if(op == 3){
read(u);read(v);read(op);
if(findRoot(mem+u) == findRoot(mem+v)) inc(mem+u,mem+v,op);
}else if(op == 4){
read(u);read(v);
if(findRoot(mem+u) == findRoot(mem+v)) query(mem+u,mem+v);
else puts("-1");
}
}
getchar();getchar();
return 0;
}
bzoj 3091: 城市旅行 LCT的更多相关文章
- BZOJ 3091: 城市旅行 [LCT splay 期望]
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1454 Solved: 483[Submit][Status][Discuss ...
- 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 [思路] 膜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 ...
- 【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& ...
- 【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区间合并 前三个 ...
随机推荐
- 九度OJ 1188:约瑟夫环 (约瑟夫环)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1891 解决:817 题目描述: N个人围成一圈顺序编号,从1号开始按1.2.3......顺序报数,报p者退出圈外,其余的人再从1.2.3 ...
- images have the “stationarity” property, which implies that features that are useful in one region are also likely to be useful for other regions.
Convolutional networks may include local or global pooling layers[clarification needed], which combi ...
- 【译】Java语言速览:StackOverflow
Java (请不要与 JavaScript 搞混) 是一种设计为与 Java 虚拟机 (JVM) 一起使用的多用途编程语言.一般称呼安装了相关工具使其可以开发并运行 Java 程序的电脑系统为 &qu ...
- CMDB的四种模式
为什么要有CMDB? CMDB --Configuration Management Database 配置管理数据库. 1.为了实现资产的自动采集,资产的自动更新, 为了搭建公司自动化平台的基础则需 ...
- Android系统字体规范
我们在做Android移动APP设计的时候,字号的选择也是很让人头疼,转载一份有关Android系统字体规范,如果在做Android项目的用户应该看看,如果有任何建议欢迎在留言处与我们交流探讨. 主要 ...
- 遇到IIS configuration error错误的可以看看,不一定是权限问题
最近接手了别人的一个 DOT NET项目,编译.调试一切都OK(心里暗暗高兴),发布吧,结果放到服务器上一运行出现Configuration Error错误,提示:“Access to the pat ...
- Django模型系统——ORM
一.概论 1.ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描 ...
- Python基础(2)_数字和字符串类型
一.数据类型 1.数字 整型 Python的整型相当于C中的long型,Python中的整数可以用十进制,八进制,十六进制表示. >>> --------->默认十进制 > ...
- Linux基础系列:常用命令(8)_shell script
一.什么是shell script 将OS命令堆积到可执行的文件里,由上至下的顺序执行文本里的OS命令 就是脚本了. 再加上些智能(条件/流控)控制,就变成了智能化脚本了 二.变量命名规则 以字母或下 ...
- spring mvc入门教程 转载自【http://elf8848.iteye.com/blog/875830】
目录 一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 ...