「2018山东一轮集训」 Tree
为什么出题人这么毒瘤啊??!!一个分块还要带log的题非要出成n<=2*1e5。。。。。。。
为了卡过最后两个点我做了无数常数优化,包括但不限于:把所有线段树改成 存差分的树状数组;把树剖求LCA的极小的log优化成rmq O(1)求LCA;根据测试情况手动调整siz的大小;
但就是死也卡不过去,算了算了QWQ
(常规套路,先把1设成根建有根树)
这个题的主要思路就是 对节点的下标分块,设 f[i][j] 为 第i个块内所有点到点j的距离和,然后看如何快速的动态维护这个玩意。。。。
发现改动一条边权的时候,只有两个点分别位于这条边两侧的时候才会对它们之间的dis有影响。
我们设p为边端点中更深的那个,那么也就是一个在p子树内,一个在子树外的才有影响。。。。
于是我们对每个块开一个vector记录一下这个块内的点的dfs序集合,排完序之后就可以之间O(log)的查询某个块在一棵子树内/外的点数了。。。
因为f[][]的第一维比较小,所以我们可以暴力枚举第一维,然后对第二维进行快速的修改。。。。。这时候发现第二维如果是存dfs序的话会更加方便(子树内可以直接进行区间修改),所以就改成下标代表dfs序啦。。。
对于整块整块的一些点到某个点的距离,用上述方法就行啦。。。可以发现都是区间修改单点查询,所以用差分的树状数组可以快(可能还不止)4倍常数哦。。。
查询零散的点对(i,j)之间的距离的话更加简单。。可以动态维护dis[i]表示i到根的距离(发现也是区间修改单点查询,所以可以类似上述整块的方法处理),答案就是dis[i]+dis[j]-2*dis[LCA(i,j)]。。。
可能说起来不是很多吧qwq?但是要写一辈子啊QWQWQWQ。。。。
(我美好的下午就这么没了QWQ)
话说我把树剖求LCA改成rmq之后反而更慢了QWQ,这是什么鬼啊。。。。
/*
inside : b * derta
outside : a * derta all -> a * derta
inside -> (b-a) * derta
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#include<iostream>
#define ll long long
using namespace std;
#define pb push_back
const int maxn=200003,N=205; inline int read(){
int x=0; char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x;
} void W(ll x){ if(x>=10) W(x/10); putchar(x%10+'0');} int n,m,T,dep[maxn],siz[maxn],cl[maxn];
int F[maxn],dc,dfn[maxn],dy[maxn],son[maxn];
int bl[maxn],num,val[maxn*2],uu,vv,ww;
int hd[maxn],ne[maxn*2],to[maxn*2];
ll ans=0,f[N][maxn];
vector<int> id[N];
char s[10]; void add(const int &x,const int &y,const int &z){
to[++num]=y,ne[num]=hd[x],hd[x]=num,val[num]=z;
} void update(const int &T,int x,const int &y){ for(;x<=n;x+=x&-x) f[T][x]+=(ll)y;}
ll query(const int &T,int x){ ll an=0; for(;x;x-=x&-x) an+=(ll)f[T][x]; return an;} void Fdfs(int x,int fa){
F[x]=fa,siz[x]=1;
for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){
dep[to[i]]=dep[x]+1,Fdfs(to[i],x),siz[x]+=siz[to[i]];
if(!son[x]||siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
} void Sdfs(int x,int tp){
dfn[x]=++dc,dy[dc]=x,cl[x]=tp; if(!son[x]) return; Sdfs(son[x],tp); for(int i=hd[x];i;i=ne[i])
if(to[i]!=F[x]&&to[i]!=son[x]) Sdfs(to[i],to[i]);
} inline int LCA(int a,int b){
while(cl[a]!=cl[b]){
if(dep[cl[a]]>dep[cl[b]]) a=F[cl[a]];
else b=F[cl[b]];
}
return dep[a]>dep[b]?b:a;
} inline int Get(int T,int x){
return upper_bound(id[T].begin(),id[T].end(),x)-id[T].begin();
} inline void Maintain(int o,int derta){
int p=to[o*2-1];
if(dep[p]<dep[to[o<<1]]) p=to[o<<1]; update(0,dfn[p],derta),update(0,dfn[p]+siz[p],-derta); for(int i=1,a,b;i<=200;i++) if(id[i].size()){
a=Get(i,dfn[p]+siz[p]-1)-Get(i,dfn[p]-1),b=id[i].size()-a;
update(i,1,a*derta),update(i,dfn[p],(b-a)*derta),update(i,dfn[p]+siz[p],(a-b)*derta);
}
} inline ll calc(int qz,int p){
ll an=0; for(int i=1;i<bl[qz];i++) an+=query(i,dfn[p]); for(int i=qz;i;i--){
an+=query(0,dfn[i])+query(0,dfn[p])-2ll*query(0,dfn[LCA(p,i)]);
if(bl[i]!=bl[i-1]) break;
} return an;
} inline void prework(){
Fdfs(1,0),Sdfs(1,1); for(int i=1;i<=n;i++){
bl[i]=(i-1)/1000+1;
id[bl[i]].pb(dfn[i]);
}
for(int i=1;i<=200;i++) sort(id[i].begin(),id[i].end()); for(int i=1;i<n;i++) Maintain(i,val[i<<1]);
} inline void solve(){
const int ha=n; while(m--){
scanf("%s",s);
if(s[0]=='m'){
uu=read(),vv=read();
if(T) uu^=ans,vv^=ans; Maintain(uu,vv-val[uu<<1]),val[uu<<1]=vv;
}
else{
uu=read(),vv=read(),ww=read();
if(T) uu^=ans,vv^=ans,ww^=ans; ans=calc(vv,ww)-calc(uu-1,ww); W(ans),puts(""),ans%=ha;
}
}
} int main(){
// freopen("tree.in","r",stdin);
// freopen("tree.out","w",stdout); n=read(),m=read(),T=read(); for(int i=1;i<n;i++){
uu=read(),vv=read(),ww=read();
add(uu,vv,ww),add(vv,uu,ww);
} prework(); solve(); return 0;
}
「2018山东一轮集训」 Tree的更多相关文章
- 「2018山东一轮集训」Game
%%神仙题 首先转化一波模型:可以把原问题看成,初始每个位置有0/1个石子,1操作看成从一个位置拿走一个石子,2操作看成从l[i]拿走一个石子,并在[ l[i]+1 , r[i] ]的每个位置放上一个 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
- 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)
[LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...
- loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流
loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...
- LOJ #6074. 「2017 山东一轮集训 Day6」子序列
#6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...
- 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP
[LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...
随机推荐
- 【洛谷 P3628】 [APIO2010]特别行动队 (斜率优化)
题目链接 斜率优化总结待补,请催更.不催更不补 \[f[i]=f[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c\] \[=f[j]+a*sum[i]^2+a*s ...
- python初步学习-pycharm使用 (二)
pycharm调试模式 假设我们的程序在运行过程中命中了一个错误,那我们如何定位错误发生的位置?这就需要进行调试. 在Pycharm中我们可以在其中直接对程序进行调试,唯一需要做的准备工作就是在程序必 ...
- hdu 1233 还是畅通工程 (最小生成树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1233 还是畅通工程 Time Limit: 4000/2000 MS (Java/Others) ...
- Android Studio注意事项
http://www.android-studio.org/ 解决方法: 在 Android Studio 安装目录 bin/idea.properties 文件最后追加一句 1 disable.an ...
- 限制printk打印频率函数printk_ratelimit【转】
转自:http://blog.csdn.net/lkkey80/article/details/45190095 版权声明:博文地址 http://blog.csdn.net/lkkey80?view ...
- Git常规配置与基本用法
Git环境配置 一. 全局配置 1. 配置文件 git全局配置文件.gitconfig默认在当前系统用户文件夹下,window可运行%USERPROFILE%查找,Mac系统在cd ~查找. 具体配置 ...
- mips64高精度时钟引起ktime_get时间不准,导致饿狗故障原因分析【转】
转自:http://blog.csdn.net/chenyu105/article/details/7720162 重点关注关中断的情况.临时做了一个版本,在CPU 0上监控所有非0 CPU的时钟中断 ...
- 学习 Linux,101: 自定义或编写简单脚本【转】
转自:http://www.ibm.com/developerworks/cn/linux/l-lpic1-105-2/index.html 学习如何使用标准的 shell 语法.循环和控制结构,以及 ...
- 深度解析Python动态语言
1.动态语言的定义 动态编程语言是高级程序设计语言的一个类别,在计算机科学领域已被广泛应用.它是一类在运行时可以改变其结构的语言:例如新的函数.对象.甚至代码可以被引进,已有的函数可以被删除或是其他结 ...
- 【LabVIEW技巧】工厂模式_简单工厂
前言 上一个文章介绍了如何学习LabVIEW OOP,简要的提及了一些OOP学习中注意的事项,许多文章的读者反映写的太范,后文会逐步缩小范围,讨论在LabVIEW中各个模式的应用. 工厂模式概述 工厂 ...