3091: 城市旅行

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2251  Solved: 761
[Submit][Status][Discuss]

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

Source

wyx528命题

题解:

  给出一个无根树,维护四个操作,link,cut,路径加法,路径期望查询,前三个都是LCT的基本操作(LCT见前面的随笔),主要说第四个;

对于路径期望,如果两点之间的点数为n,那么很明显是C(n+1,2)=n*(n+1)/2;考虑维护分子:

如图所示,考虑求每个点的贡献,然后求和;第一个点对答案的贡献为a1*1*n(左端点只能选a1,右端点可以选a1~an),

第二个点对答案的贡献为a2*2*(n-1)(左端点可以选a1或a2,右端点可以选a2~an)

于是答案就是a1*1*n+a2*2*(n-1)+...+an*n*1 这个东西显然不能暴力求 需要在LCT上维护 但是直接维护根本维护不了 怎么办呢?

观察左子树 将左子树合并前后的贡献值作差可得

  我们发现这个3其实就是右子树的size+1

  于是我们们令lsum=1*a1+2*a2+3*a3...+n*an;      rsum=n*a1+(n-1)*a2+...+1*an;

则:root.ans=lson.ans+lson.lsum*(rson.size+1)  +  rson.ans+rson.rsum*(lson.size+1)  +  root.sum*(lson.size+1)*(rson.size+1) (左子树贡献+右子树的贡献+根节点的贡献);

考虑对于lsum和rsum的维护,lsum的维护为root.lsum = lson.lsum+root.val*(lson.size+1) + rson.lsum + rson.sum*(lson.size+1);

对于rsum 的维护类似: root.rsum = rson.rsum + root.val*(son.size+1) + lson.rsum + lson.sum*(rson.size+1);

当对于root为根的整棵树更新的时候root.ans的维护为:加 val*(1*n+2*(n-1)+3*(n-2)+...+n*1)=val*n*(n+1)*(n+2)/6(这里的n=root.size)。

1$*$n+2$*$(n-1)+3$*$(n-2)+...+n$*$1

=(1+2+3+...+n)$*$n-(1$*$2+2$*$3+3$*$4+...+(n-1)$*$n)

=${n^2*(n+1)\over 2}$-(1$^2$+2$^2$+3$^2$+...+(n-1)$^2$+1+2+3+...+(n-1))

=$n^2*(n+1)\over 2$-$n*(n-1)*(2*n-1)\over 6$ -$n*(n-1)\over 2$

=$(3*n(n+1)-n*(n-1)*(2*n-1)-3*n*(n-1))\over 6$

=$n*(n^2+3*n+2)\over 6​$

=$n*(n+1)*(n+2)\over 6$

参考代码:

  1 /**************************************************************
  2     Problem: 3091
  3     User: SongHL
  4     Language: C++
  5     Result: Accepted
  6     Time:1764 ms
  7     Memory:6464 kb
  8 ****************************************************************/
  9
 10 //BZOJ 3091
 11 //给出一棵无根树,维护四个操作:link,cut,路径加法,路径期望查询
 12 #include<bits/stdc++.h>
 13 #define LL long long
 14 #define inf 2147483640
 15 #define Pi acos(-1.0)
 16 using namespace std;
 17 const int maxn=50010;
 18 int n,m,fa[maxn];
 19 struct node{
 20     int son[2];
 21     LL sum,tag,rev,ans,val,lsum,rsum,size;
 22     int& operator [] (int x) {return son[x];}
 23 }tree[maxn];
 24 LL gcd(LL a,LL b) {return b==0 ? a : gcd(b,a%b);}
 25 namespace LCT{
 26     void reverse(int k)
 27     {
 28         swap(tree[k][0],tree[k][1]);
 29         swap(tree[k].lsum,tree[k].rsum);
 30         tree[k].rev^=1;
 31     }
 32
 33     void add(int k,LL val)
 34     {
 35         tree[k].val+=val;
 36         tree[k].sum+=tree[k].size*val;
 37         tree[k].tag+=val;
 38         tree[k].ans+=tree[k].size*(tree[k].size+1)*(tree[k].size+2)/6*val;
 39         tree[k].lsum+=tree[k].size*(tree[k].size+1)/2*val;
 40         tree[k].rsum+=tree[k].size*(tree[k].size+1)/2*val;
 41     }
 42     int find(int x) {return fa[x] ? find(fa[x]):x;}
 43
 44     void pushdown(int k)
 45     {
 46         if(tree[fa[k]][0]==k || tree[fa[k]][1]==k) pushdown(fa[k]);
 47         int l=tree[k][0],r=tree[k][1];
 48         if(tree[k].rev)
 49         {
 50             if(l) reverse(l);
 51             if(r) reverse(r);
 52             tree[k].rev^=1;
 53         }
 54         if(tree[k].tag)
 55         {
 56             if(l) add(l,tree[k].tag);
 57             if(r) add(r,tree[k].tag);
 58             tree[k].tag=0;
 59         }
 60     }
 61     void pushup(int k)
 62     {
 63         int l=tree[k][0],r=tree[k][1];
 64         tree[k].size=tree[l].size+tree[r].size+1;
 65         tree[k].lsum=tree[l].lsum+(tree[l].size+1)*tree[k].val+tree[r].lsum+tree[r].sum*(tree[l].size+1);
 66         tree[k].rsum=tree[r].rsum+(tree[r].size+1)*tree[k].val+tree[l].rsum+tree[l].sum*(tree[r].size+1);
 67         tree[k].sum=tree[l].sum+tree[r].sum+tree[k].val;
 68         tree[k].ans=tree[l].ans+tree[r].ans+tree[l].lsum*(tree[r].size+1)+tree[r].rsum*(tree[l].size+1)+tree[k].val*(tree[l].size+1)*(tree[r].size+1);
 69     }
 70     void rotate(int x)
 71     {
 72         int y=fa[x],z=fa[y],l,r;
 73         l=tree[y][1]==x;r=l^1;
 74         if(tree[z][0]==y || tree[z][1]==y) tree[z][tree[z][1]==y]=x;
 75         fa[tree[x][r]]=y;fa[x]=z;fa[y]=x;
 76         tree[y][l]=tree[x][r];tree[x][r]=y;
 77         pushup(y);pushup(x);
 78     }
 79     void splay(int x)
 80     {
 81         pushdown(x);
 82         while(tree[fa[x]][0]==x || tree[fa[x]][1]==x)
 83         {
 84             int y=fa[x],z=fa[y];
 85             if(tree[z][0]==y || tree[z][1]==y)
 86             {
 87                 if(tree[z][0]==y^tree[y][0]==x) rotate(x);
 88                 else rotate(y);
 89             }
 90             rotate(x);
 91         }
 92     }
 93     void access(int x) //访问
 94     {
 95         for(int y=0;x;y=x,x=fa[x]) splay(x),tree[x][1]=y,pushup(x);
 96     }
 97     int findroot(int x)//找根(在真实的树中的)
 98     {
 99         access(x);splay(x);
100         while(tree[x][0]) pushdown(x),x=tree[x][0];
101         return x;
102     }
103     void makeroot(int x) //换根
104     {
105         access(x);splay(x);reverse(x);
106     }
107     void split(int x,int y)//提取路径
108     {
109         makeroot(x);
110         access(y);splay(y);
111     }
112     void link(int x,int y)
113     {
114         makeroot(x);fa[x]=y;
115     }
116     void cut(int x,int y)
117     {
118         makeroot(x);access(y);splay(y);
119         if(tree[y][0]==x && tree[x][1]==0)
120             tree[y][0]=0,fa[x]=0,pushup(y);
121     }
122     void modify(int x,int y,LL val)//对x~y这段路径操作
123     {
124         makeroot(x);access(y);
125         splay(y);add(y,val);
126     }
127     void query(int x,int y)
128     {
129         split(x,y);
130         LL A=tree[y].ans,B=tree[y].size*(tree[y].size+1)/2;
131         LL D=gcd(A,B);
132         printf("%lld/%lld\n",A/D,B/D);
133     }
134 }
135 using namespace LCT;
136
137 int main()
138 {
139     scanf("%d%d",&n,&m);
140     for(int i=1;i<=n;i++) scanf("%lld",&tree[i].val);
141     for(int u,v,i=1;i<n;i++)
142     {
143         scanf("%d%d",&u,&v);
144         link(u,v);
145     }
146     for(int op,x,y,d,i=1;i<=m;i++)
147     {
148         scanf("%d%d%d",&op,&x,&y);
149         if(op==1) if(find(x)==find(y)) cut(x,y);
150         if(op==2) if(find(x)!=find(y)) link(x,y);
151         if(op==3){ scanf("%d",&d); if(find(x)==find(y)) modify(x,y,d); }
152         if(op==4) if(find(x)==find(y)) query(x,y); else puts("-1");
153     }
154     return 0;
155 }

View Code

  

转载于:https://www.cnblogs.com/songorz/p/9912208.html

BZOJ 3091 城市旅行 (LCT)相关推荐

  1. BZOJ 3091: 城市旅行 LCT

    这个合并还是相当复杂的. code: #include <cstdio> #include <cstring> #include <string> #include ...

  2. bzoj 3091 城市旅行

    3091: 城市旅行 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1697  Solved: 565 [Submit][Status][Discu ...

  3. BZOJ 3091 城市旅行 Link-Cut-Tree

    警告:此题不可以使用cout进行输出,只能用printf,否则RE!亲测!! 题目大意:给定一棵树,每个点有一个点权,提供四种操作: 1.删除两点之间的连边 不存在边则无视 2.在两点之前连接一条边 ...

  4. BZOJ 3531[Sdoi2014]旅行

    BZOJ 3531[Sdoi2014]旅行 题面描述 传送门 题目分析 可以考虑到,如果这个题所有城市都只信一种宗教的话,就是一个sb树剖,直接进行链的查询和修改就能搞定.多个宗教的话,可以有一种暴力 ...

  5. 【BZOJ3091】城市旅行

    [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 ...

  6. [BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】

    题目链接:BZOJ - 3531 题目分析 题目询问一条路径上的信息时,每次询问有某种特定的文化的点. 每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息. 可以使用离线算法, 类似于 ...

  7. [BZOJ3091][LCT]城市旅行

    BZOJ3091 LCT简单题 计算期望比较简单吧,都是平衡树基操 但是BZOJ算总时间过了,单点有的我要跑1.5s Code: #include<bits/stdc++.h> #defi ...

  8. 【LCT】城市旅行(luogu 4842/金牌导航 LCT-3)

    正题 luogu 4842 金牌导航 LCT-3 题目大意 给你一棵树,让你进行一些操作: 1.删除一条边 2.连接一条边 3.给一条路径上的点加上x 4.给出一条路径,在该路径选取两个点,求这两个点 ...

  9. 基于机器学习预测Airbnb的城市旅行成本

    本文为翻译发表,转载需要注明来自公众号EAWorld. 作者:Sean Kim 译者:白小白 原题:一文了解Airbnb的旅行成本 原文:http://t.cn/E2FvawU 全文3538字,阅读约 ...

最新文章

  1. OpenGL渲染流水中的处理步骤
  2. 神经网络的输入对迭代次数的影响
  3. html 3d转换动画,开源项目:CSS 3D转换和动画学习示例教程
  4. navicat mysql两张表建立联系_初识MySQL
  5. android清空frame,android – GLSurfaceView onDrawFrame清除行为
  6. Android内存解析(二)— 详解内存,内部存储和外部存储
  7. 元璟资本陈洪亮解析人货场融合 消费者变成“合作者”
  8. js 面向对象 继承
  9. 错误提示 - WPS Office 文字 正在运行
  10. 15个android框架,Android常用的15个框架总结
  11. linux高性能集群搭建,sge linux高性能集群的搭建与使用
  12. python中with open as f什么意思_Python中 with open(file_abs,'r') as f: 的用法以及意义
  13. 强大的图片预览组件Viewer.js
  14. border渐变 ios_IOS画渐变的三种方式
  15. 安装tensorflow报错
  16. 单片机编程:如何喂狗的灵魂拷问...
  17. matlab下载小木虫,小木虫关于fluent知识集合-个人总结
  18. 独家 | 利用深度学习来预测Spotify上的Hip-Hop 流行程度
  19. 群策CRM解决方案,直击系统集成行业风口
  20. 原生js 时间字符串转日期,月份错误(setMonth)

热门文章

  1. GFS分布式文件系统
  2. ESD导致空调控制面板控制失效问题分析与解决
  3. delphi 二代身份证阅读器开发 SDT_ReadBaseMsg函数
  4. 在腾讯和网易快吃光游戏下,区块链游戏是较好的机会
  5. 小刘同学的第八十篇博文
  6. STM32用pwm开环控制电机如何接线(有图解)
  7. C语言实现基于easyx的(低配版)黄金矿工游戏
  8. 多线程高并发编程(10) -- ConcurrentHashMap源码分析
  9. 使用ts_calibrate校准触摸屏
  10. 护理等级分级标准及巡视时间_18项护理核心制度,都在这了