BZOJ 3159: 决战

1 sec 512MB

题意:

给你一颗\(n\)个点,初始点权为\(0\)的有跟树,要求支持

  • Increase x y w 将路径\(x\)到\(y\)所有点点权加上\(w\)
  • Sum x y 询问路径\(x\)到\(y\)的点权和
  • Major x y 询问从路径\(x\)到\(y\)最大点权
  • Minor x y 询问最小点权
  • Invert x y 将路径上的点权翻转

有个性质,修改操作一定满足\(x\)为\(y\)祖先或者\(y\)为\(x\)祖先(实际没什么用处)

\(n\le 50000,|w|\le 1000\)

输入格式

第一行有三个整数\(N\)、\(M\)和\(R\),分别表示树的节点数、指令和询问总数,以及树的跟。

接下来\(N-1\)行,每行两个整数\(u\)和\(v\),表示一条边。

接下来\(M\)行,每行描述一个指令或询问,格式见题意描述。

输出格式

对于每个询问操作,输出所求的值。


老年菜鸡选手实在写不动大数据结构题...

有两个做法,暂时只写了一种,有可能一会儿会把另一种补充一下。

考虑树链剖分,但是不能维护翻转

考虑平衡树可以维护翻转

于是我们可以拿平衡树维护树剖的每条链

然后每次修改只有\(\log\)条链,我们把每条链要修改的地方拎出来,然后塞到一个平衡树里面,打一个翻转tag,再塞回去就可以了

用fhqtreap实现起来比较方便

说起来蛮简单,写起来还是蛮难受的的


Code:

#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define ll long long
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{int f=0;x=0;char c=gc();while(!isdigit(c)) f|=c=='-',c=gc();while(isdigit(c)) x=x*10+c-'0',c=gc();if(f) x=-x;
}
void reads(char *s)
{int k=0;char c=gc();while(c<'A'||c>'Z') c=gc();while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) s[k++]=c,c=gc();
}
const int N=5e4+10;
inline void ckmax(int &x,int y){x=x>y?x:y;}
inline void ckmin(int &x,int y){x=x<y?x:y;}
int n,m,r,root[N];
namespace treap
{int ch[N][2],mx[N],mi[N],siz[N],val[N],dat[N],tag[N],reve[N],tot;ll sum[N];#define ls ch[now][0]#define rs ch[now][1]void updata(int now){sum[now]=sum[ls]+dat[now]+sum[rs];siz[now]=siz[ls]+1+siz[rs];mx[now]=mi[now]=dat[now];if(ls){ckmax(mx[now],mx[ls]);ckmin(mi[now],mi[ls]);}if(rs){ckmax(mx[now],mx[rs]);ckmin(mi[now],mi[rs]);}}void Reverse(int now){std::swap(ls,rs),reve[now]^=1;}void upt(int now,int d){dat[now]+=d;tag[now]+=d;mi[now]+=d;mx[now]+=d;sum[now]+=d*siz[now];}void pushdown(int now){if(reve[now]){if(ls) Reverse(ls);if(rs) Reverse(rs);reve[now]=0;}if(tag[now]){if(ls) upt(ls,tag[now]);if(rs) upt(rs,tag[now]);tag[now]=0;}}void split(int now,int &x,int &y,int k){if(!now){x=y=0;return;}pushdown(now);if(k<=siz[ls])y=now,split(ls,x,ch[y][0],k);elsex=now,split(rs,ch[x][1],y,k-siz[ls]-1);updata(now);}int Merge(int x,int y){if(!x||!y) return x^y;pushdown(x),pushdown(y);if(val[x]<val[y]){ch[x][1]=Merge(ch[x][1],y);updata(x);return x;}else{ch[y][0]=Merge(x,ch[y][0]);updata(y);return y;}}int New(int d){val[++tot]=rand(),siz[tot]=1,sum[tot]=mi[tot]=mx[tot]=dat[tot]=d;return tot;}void ins(int id,int d){root[id]=Merge(root[id],New(d));}ll querysum(int id,int l,int r){int x,y,z;split(root[id],x,y,r);split(x,x,z,l-1);ll ret=sum[z];root[id]=Merge(x,Merge(z,y));return ret;}int querymi(int id,int l,int r){int x,y,z;split(root[id],x,y,r);split(x,x,z,l-1);int ret=mi[z];root[id]=Merge(x,Merge(z,y));return ret;}int querymx(int id,int l,int r){int x,y,z;split(root[id],x,y,r);split(x,x,z,l-1);int ret=mx[z];root[id]=Merge(x,Merge(z,y));return ret;}void modify(int id,int l,int r,int w){int x,y,z;split(root[id],x,y,r);split(x,x,z,l-1);upt(z,w);root[id]=Merge(x,Merge(z,y));}
}
using treap::modify;
using treap::querysum;
using treap::querymi;
using treap::querymx;
using treap::ins;
using treap::Merge;
using treap::split;
using treap::Reverse;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int top[N],ws[N],siz[N],par[N],dep[N],rk[N],num[N];
void dfs(int now)
{siz[now]=1;dep[now]=dep[par[now]]+1;for(int v,i=head[now];i;i=Next[i])if((v=to[i])!=par[now]){par[v]=now;dfs(v);siz[now]+=siz[v];if(siz[ws[now]]<siz[v]) ws[now]=v;}
}
int lin,tot[N];
void dfs(int now,int id,int anc)
{top[now]=anc;num[now]=id;rk[now]=++tot[id];ins(id,0);if(ws[now]) dfs(ws[now],id,anc);for(int v,i=head[now];i;i=Next[i])if(!num[v=to[i]])dfs(v,++lin,v);
}
void modi(int x,int y,int w)
{if(dep[x]<dep[y]) std::swap(x,y);while(top[x]!=top[y]){modify(num[x],1,rk[x],w);x=par[top[x]];}if(dep[x]<dep[y]) std::swap(x,y);modify(num[x],rk[y],rk[x],w);
}
void qrysum(int x,int y)
{ll ret=0;while(top[x]!=top[y]){if(dep[top[x]]>dep[top[y]]){ret+=querysum(num[x],1,rk[x]);x=par[top[x]];}else{ret+=querysum(num[y],1,rk[y]);y=par[top[y]];}}if(dep[x]<dep[y]) std::swap(x,y);ret+=querysum(num[x],rk[y],rk[x]);printf("%lld\n",ret);
}
void qrymx(int x,int y)
{int ret=-(1<<30);while(top[x]!=top[y]){if(dep[top[x]]>dep[top[y]]){ckmax(ret,querymx(num[x],1,rk[x]));x=par[top[x]];}else{ckmax(ret,querymx(num[y],1,rk[y]));y=par[top[y]];}}if(dep[x]<dep[y]) std::swap(x,y);ckmax(ret,querymx(num[x],rk[y],rk[x]));printf("%d\n",ret);
}
void qrymi(int x,int y)
{int ret=1<<30;while(top[x]!=top[y]){if(dep[top[x]]>dep[top[y]]){ckmin(ret,querymi(num[x],1,rk[x]));x=par[top[x]];}else{ckmin(ret,querymi(num[y],1,rk[y]));y=par[top[y]];}}if(dep[x]<dep[y]) std::swap(x,y);ckmin(ret,querymi(num[x],rk[y],rk[x]));printf("%d\n",ret);
}
void rev(int x,int y)
{int tx=x,ty=y;if(dep[x]<dep[y]) std::swap(x,y);int rt=0;while(top[x]!=top[y]){int id=num[x],k=rk[x],pre;split(root[id],pre,root[id],k);rt=Merge(pre,rt);x=par[top[x]];}if(dep[x]<dep[y]) std::swap(x,y);int id=num[x],l=rk[y],r=rk[x],a,b,c;split(root[id],a,c,r);split(a,a,b,l-1);rt=Merge(b,rt);Reverse(rt);x=tx,y=ty;if(dep[x]<dep[y]) std::swap(x,y);while(top[x]!=top[y]){int id=num[x],k=rk[x],pre;split(rt,rt,pre,treap::siz[rt]-k);root[id]=Merge(pre,root[id]);x=par[top[x]];}id=num[x];root[id]=Merge(a,Merge(rt,c));
}
int main()
{//freopen("data.in","r",stdin);//freopen("data.out","w",stdout);read(n),read(m),read(r);for(int u,v,i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);dfs(r);dfs(r,++lin,r);char op[23];for(int x,y,w,i=1;i<=m;i++){reads(op),read(x),read(y);if(op[0]=='I'){if(op[2]=='c') read(w),modi(x,y,w);else rev(x,y);}else if(op[0]=='S') qrysum(x,y);else{if(op[1]=='a') qrymx(x,y);else qrymi(x,y);}}return 0;
}

2019.5.22

转载于:https://www.cnblogs.com/butterflydew/p/10907764.html

BZOJ 3159: 决战 解题报告相关推荐

  1. BZOJ 2959: 长跑 解题报告

    2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...

  2. BZOJ 4238 电压 解题报告

    BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...

  3. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  4. 【解题报告系列】超高质量题单 + 题解(ACM / OI)超高质量题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我新写的超高质量的题解和代码,题目难度不 ...

  5. 解题报告(三)多项式求值与插值(拉格朗日插值)(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  6. 解题报告(十三)中国剩余定理(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  7. 解题报告(四)生成函数(ACM/ OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  8. 解题报告(八) prufer 序列与 Cayley 公式(ACM / OI)超高质量题解

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  9. 解题报告(一)E、(BZOJ4589)Hard Nim(博弈论 + FWT)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

最新文章

  1. 红旗linuxcentos_用红旗Linux 11的体验报告,附使用红旗Linux 11截图
  2. Linux之查看目录命令
  3. 地区的json数据_Python 连接开放航空交通数据,轻松构建航班跟踪应用!
  4. 苏州php速成,PHP入门速成
  5. Faster-RCNN学习
  6. 浅析软件项目管理中十个误区(来自:http://manager.csdn.net/n/20051213/30907.html)
  7. TypeScript 2.8引入条件类型
  8. 协程-gevent(python版)
  9. php环境模拟stphp_用php模拟做服务端侦听端口
  10. 转载:Pixhawk源码笔记七:姿态控制预览
  11. 2015C蓝桥杯C++A:格子中输出(详细讲解)
  12. Android游戏开发中使用Libgdx引擎遇到的问题及解决办法汇总
  13. CREO图文教程:利用CREO软件实现模型零件设计实例大全(曲柱、矿泉水瓶、三弯管、风扇叶、一腔多模、螺旋弹簧、数字刻度、足球设计、齿轮参数化设计、油缸)等几十个案例之详细攻略
  14. 杰理之设置立体声输出,播左右声道歌曲后DAC没有声音或声音变小
  15. 【淘宝补单】操作干预单不能在犯的错误
  16. Windows自带虚拟化服务工具Hyper-V学习了解和实操
  17. Win7系统如何用记事本打开文件?
  18. 20T数据迁移经验:手把手教你群晖NAS数据迁移,黑裙晖通用!
  19. python最简单的图形编程_图形化编程、Python、Java、C++到底哪个适合你?
  20. 数据库总结(五):创建与使用视图

热门文章

  1. 用Python求e的近似值
  2. java唯一id_生成唯一ID的四种办法 程序员必备
  3. 汽车变速器测试系统ETest
  4. Linux TC 带宽管理队列规则
  5. 【CSS特效扫盲】精选40种纯CSS特效应用实例,肝了10个晚上整理纯CSS特效(上)(附源码下载)
  6. 工业物联网数控机床设备远程控制整体解决方案
  7. 雷军:何以英雄背骂名!
  8. HTML5+CSS3小实例:炫彩的聚光灯文字效果
  9. UE4 如何旋转模型骨骼
  10. 文旅灯光秀应该怎样进行设计