左偏树裸题 合并+lazytag即可
每个点合并儿子然后弹出所有<ci的即可
然后每个骑士直接dep[x]-dep[y]挂了的节点和初始节点的深度差即可
样例太水了注意要判每个节点万一骑士挂完了是空的QAQ
//Love and Freedom.#include#include #include #include #define ll long long#define inf 20021225#define N 300010using namespace std;ll read(){ ll s=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return f*s;}struct edge{ int to,lt;}e[N]; int in[N],cnt,dep[N]; int rt[N];void add(int x,int y){e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;} struct node{ll val,mul,add; int fa,son[2],dis;}t[N];int st[N]; int war[N],city[N]; ll v[N],c[N]; bool kd[N];void pushdown(int x){ int ls=t[x].son[0],rs=t[x].son[1]; ll mul=t[x].mul,add=t[x].add; if(mul!=1) { t[ls].val*=mul; t[rs].val*=mul; t[ls].mul*=mul; t[rs].mul*=mul; t[ls].add*=mul; t[rs].add*=mul; t[x].mul=1; } if(add) { t[ls].val+=add; t[rs].val+=add; t[ls].add+=add; t[rs].add+=add; t[x].add=0; }}int find(int x){ return t[x].fa^x?t[x].fa=find(t[x].fa):x;}int merge(int x,int y){ if(!x||!y) return x|y; if(t[x].val>t[y].val) swap(x,y); pushdown(x); t[x].son[1]=merge(t[x].son[1],y); t[t[x].son[1]].fa=t[t[x].son[0]].fa=x; t[x].fa=x; if(t[t[x].son[1]].dis>t[t[x].son[0]].dis) swap(t[x].son[0],t[x].son[1]); t[x].dis=t[t[x].son[1]].dis+1; return x;}void modify(int x,ll add,ll mul){ if(mul!=1){t[x].val*=mul; t[x].mul*=mul; t[x].add*=mul;} if(add){t[x].val+=add; t[x].add+=add;}}void pop(int &x,int ct){ war[x]=dep[st[x]]-dep[ct]; city[ct]++; pushdown(x); t[t[x].son[0]].fa=t[x].son[0]; t[t[x].son[1]].fa=t[x].son[1]; t[x].fa=merge(t[x].son[0],t[x].son[1]); t[t[x].fa].fa=t[x].fa; x=t[x].fa;}void work(int x){ for(int i=in[x];i;i=e[i].lt) dep[e[i].to]=dep[x]+1,work(e[i].to),rt[x]=merge(rt[x],rt[e[i].to]); while(rt[x]&&t[rt[x]].val