题解
此题的一种经典做法:套两颗LCT,一颗维护权值,一颗维护形态。
形态树里的每一个节点都有一个对应的权值树里的点。
对于值的区间翻转,只翻转权值树。其他操作则两棵树一起操作。
在形态树中操作时,对于节点之间关系的修改,对应权值中的点可以通过bst找k大完成。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int N=5e4+10;
const ll inf=1LL<<60;
int n,m,R;
char s[12];
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){
if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
struct Ta{
struct Node{
Node *ch[2],*f;int sz,rv;
ll ad,v,mn,mx,sum;
void reverse(){
rv^=1;swap(ch[0],ch[1]);
}
void update(){
sz=ch[0]->sz+1+ch[1]->sz;
sum=ch[0]->sum+v+ch[1]->sum;
mn=min(min(ch[0]->mn,ch[1]->mn),v);
mx=max(max(ch[0]->mx,ch[1]->mx),v);
}
void change(int w){
ad+=w;v+=w;mn+=w;mx+=w;sum+=1ll*sz*w;
}
void pushdown(Node *null){
if(rv){
if(ch[0]!=null) ch[0]->reverse();
if(ch[1]!=null) ch[