Description

树上链翻转,链加,查询链上的和/max/min

树链剖分套treap,修改查询可以用类似线段树的写法,翻转可以利用分裂合并和翻转标记实现,时间复杂度O(nlog2n)

实测除了翻转之外的操作常数较小,翻转由于需要把整条链拆出来再合并回去,稍慢一些

#include<cstdio>
#include<algorithm>
typedef long long i64;
const int N=;
int _(){
int x;scanf("%d",&x);return x;
}
i64 _a;
void maxs(i64&a,i64 b){if(a<b)a=b;}
void mins(i64&a,i64 b){if(a>b)a=b;}
struct node{
node*lc,*rc;
int sz,rnd,rv;
i64 a,v,s,mx,mn;
void _rev(){
if(!this)return;
rv^=;
std::swap(lc,rc);
}
void _add(i64 x){
if(!this)return;
a+=x;v+=x;
mx+=x;mn+=x;
s+=x*sz;
}
void dn(){
if(rv){
lc->_rev();
rc->_rev();
rv=;
}
if(a){
lc->_add(a);
rc->_add(a);
a=;
}
}
void up(){
sz=;s=v;
mx=mn=v;
if(lc){
sz+=lc->sz;
s+=lc->s;
maxs(mx,lc->mx);
mins(mn,lc->mn);
}
if(rc){
sz+=rc->sz;
s+=rc->s;
maxs(mx,rc->mx);
mins(mn,rc->mn);
}
}
void sp(int k,node*&l,node*&r){
if(!this){l=r=;return;}
int ls=lc?lc->sz:;
dn();
if(k<=ls)lc->sp(k,l,lc),r=this;
else rc->sp(k-ls-,rc,r),l=this;
up();
}
node*mg(node*a){
if(!a)return this;
if(!this)return a;
if(rnd>a->rnd){
dn();
rc=rc->mg(a);
up();
return this;
}
a->dn();
a->lc=mg(a->lc);
a->up();
return a;
}
#define DEF(A,B,C) \
void A(int l,int r){\if(!this||r<=||l>=sz)return;\
if(l<=&&r>=sz){B;return;}\
int ls=lc?lc->sz:;\
dn();\
if(l<=ls&&r>ls)C;\
if(l<ls)lc->A(l,r);\
if(r>ls+)rc->A(l-ls-,r-ls-);\
up();\
}
DEF(add,_add(_a),v+=_a)
DEF(gmx,maxs(_a,mx),maxs(_a,v))
DEF(gmn,mins(_a,mn),mins(_a,v))
DEF(sum,_a+=s,_a+=v)
#undef DEF
}ns[N],*rt[N];
int es[N*],enx[N*],e0[N],ep=;
int fa[N],sz[N],son[N],dep[N],top[N];
void f1(int w,int pa){
dep[w]=dep[fa[w]=pa]+;
sz[w]=;
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(u!=pa){
f1(u,w);
sz[w]+=sz[u];
if(sz[u]>sz[son[w]])son[w]=u;
}
}
}
void f2(int w,int tp){
top[w]=tp;
rt[tp]=rt[tp]->mg(ns+w);
if(son[w])f2(son[w],tp);
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(u!=fa[w]&&u!=son[w])f2(u,u);
}
}
#define DEF(A) \
void A(int x,int y){\
int a=top[x],b=top[y];\
while(a!=b){\
if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);\
rt[a]->A(,dep[x]-dep[a]+);\
x=fa[a],a=top[x];\
}\
if(dep[x]>dep[y])std::swap(x,y);\
rt[a]->A(dep[x]-dep[a],dep[y]-dep[a]+);\
}
DEF(add)
DEF(gmx)
DEF(gmn)
DEF(sum)
#undef DEF
node*s1[][],*s2[][];
int sz1[],w1[],sz2[],w2[];
void rev(int x,int y){
if(x==y)return;
int a=top[x],b=top[y],p1=,p2=;
while(a!=b){
if(dep[a]>dep[b]){
s1[p1][]=;
rt[a]->sp(dep[x]-dep[a]+,s1[p1][],s1[p1][]);
w1[p1]=a;
sz1[p1]=s1[p1][]->sz;
++p1;
x=fa[a],a=top[x];
}else{
s2[p2][]=;
rt[b]->sp(dep[y]-dep[b]+,s2[p2][],s2[p2][]);
w2[p2]=b;
sz2[p2]=s2[p2][]->sz;
++p2;
y=fa[b],b=top[y];
}
}
if(dep[x]>dep[y]){
rt[a]->sp(dep[y]-dep[a],s1[p1][],s1[p1][]);
s1[p1][]->sp(dep[x]-dep[y]+,s1[p1][],s1[p1][]);
w1[p1]=a;
sz1[p1]=s1[p1][]->sz;
++p1;
}else{
rt[a]->sp(dep[x]-dep[a],s2[p2][],s2[p2][]);
s2[p2][]->sp(dep[y]-dep[x]+,s2[p2][],s2[p2][]);
w2[p2]=a;
sz2[p2]=s2[p2][]->sz;
++p2;
}
node*p=;
for(int i=;i<p1;++i)p=s1[i][]->mg(p);
p->_rev();
for(int i=p2-;i>=;--i)p=p->mg(s2[i][]);
for(int i=;i<p1;++i)p->sp(p->sz-sz1[i],p,s1[i][]);
p->_rev();
for(int i=p2-;i>=;--i)p->sp(sz2[i],s2[i][],p);
for(int i=;i<p1;++i)rt[w1[i]]=s1[i][]->mg(s1[i][])->mg(s1[i][]);
for(int i=;i<p2;++i)rt[w2[i]]=s2[i][]->mg(s2[i][])->mg(s2[i][]);
}
int n,m,r;
char op[];
int main(){
scanf("%d%d%d",&n,&m,&r);
for(int i=;i<=n;++i)ns[i].rnd=rand()|,ns[i].sz=;
for(int i=,a,b;i<n;++i){
scanf("%d%d",&a,&b);
es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
}
f1(,);
f2(,);
while(m--){
int x,y,z;
scanf("%s%d%d",op,&x,&y);
if(op[]=='c'){
scanf("%d",&z);
_a=z;
add(x,y);
}else if(op[]=='m'){
_a=;
sum(x,y);
printf("%lld\n",_a);
}else if(op[]=='j'){
_a=-(1ll<<);
gmx(x,y);
printf("%lld\n",_a);
}else if(op[]=='n'){
_a=1ll<<;
gmn(x,y);
printf("%lld\n",_a);
}else{
rev(x,y);
}
}
return ;
}

bzoj 3159: 决战的更多相关文章

  1. BZOJ 3159: 决战 解题报告

    BZOJ 3159: 决战 1 sec 512MB 题意: 给你一颗\(n\)个点,初始点权为\(0\)的有跟树,要求支持 Increase x y w 将路径\(x\)到\(y\)所有点点权加上\( ...

  2. BZOJ 3159决战

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3159 题意:给出一棵树,(1)路径加一个值:(2)路径上的节点的值反转(只是值反转,不是节 ...

  3. bzoj 3159: 决战【LCT】

    只是想复健一下LCT没想到做了不得了的题--调了两天QAQ 题解是这么说的: 但是果然还不太理解--因为swap的前后问题调了好久,(所以一开始养成的习惯后面就不要再改啦-- 总之大概就是把对位置lc ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. Filter execute order in asp.net web api

    https://stackoverflow.com/questions/21628467/order-of-execution-with-multiple-filters-in-web-api Som ...

  2. What's the difference between SDK and Runtime in .NET Core?

    What's the difference between SDK and Runtime in .NET Core? Answer1 According to the .Net Core Guide ...

  3. NIO概述及实例(时钟服务器)

    NIO,非阻塞IO,重点是非阻塞而不是异步! NIO的一般实现如下: package com.pt.nio; import java.net.InetSocketAddress; import jav ...

  4. linux 查看数据库和表

    mysql -h localhost -u 用戶名 -p密碼                //連接數據庫use desk_show;                                 ...

  5. UVa 1637 纸牌游戏(全概率公式)

    https://vjudge.net/problem/UVA-1637 题意: 36张牌分成9堆,每堆4张牌.每次可以拿走某两堆顶部的牌,但需要点数相同.每种拿法的概率均为1/5.求成功概率. 思路: ...

  6. Kolakoski数列

    2018-04-16 15:40:16 Kolakoski序列是一个仅由1和2组成的无限数列,是一种通过“自描述”来定义的数列.他在整数数列大全网站上排名第二位,足见该数列在组合数学界中的重要性. K ...

  7. php特级课---5、网络数据转发原理

    php特级课---5.网络数据转发原理 一.总结 一句话总结: OSI七层模型 路由器 交换机 ARP 代理ARP 1.OSI7层模型? 电缆 MAC地址 ip 端口 应用 1层 通信电缆 2层 原M ...

  8. rails5.2新特性--ActiveStorage, 使用80percent/rails-template

    看guide,看ruby-China的好贴,看最新版的书上案例. 以下摘自https://ruby-china.org/topics/36666 作者lyfi2003 用户对上传文件的要求体验: 上传 ...

  9. 位于/var/log目录下的20个Linux日志文件

    位于/var/log目录下的20个Linux日志文件[译] from:http://buptguo.com/2014/01/16/linux-var-log-files/ 原文地址:20 Linux ...

  10. mysql中limit的用法详解[数据分页常用]

    在我们使用查询语句的时候,经常要返回前几条或者中间某几行的数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM table LIMIT [offset ...