倍增分块与平衡树
EnofTaiPeople · · 题解
首先发现本题每次在每次行走时都形如一个分段函数,但这个分段函数还有一个权值维,就不知道怎么维护了。
所以可以尝试将已知权值放在一起维护,像扫描线一样,将所有询问在
形如
显然每个数最多变块
考虑动态维护有序值域区间,这个用平衡树维护就可以了,因为 Splay 是相对灵活的,所以我使用了 Splay,总时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=1e9+7;
using ll=long long;
int n,m,sta[N];
struct dat{int l,r,v;}d[N];
vector<int>ad[N],dl[N];
int L[N],R[N],kt;
int t[N][2],f[N],rt[42];
#define ls t[x][0]
#define rs t[x][1]
#define tp(x) (t[f[x]][1]==x)
#define in(x) (t[f[x]][0]==x||tp(x))
int stk[N],tp;
ll t1[N],t2[N],w[N],v[N];
void ad1(int x,ll d){t1[x]+=d,v[x]-=d;}
void ad2(int x,ll d){t2[x]+=d,w[x]+=d;}
int Ik(int d){
// cerr<<d<<endl;
for(int i=kt;i;--i)
if(d>=L[i])return i;
assert(0);
return -1e9;
}
void pd(int x){
if(t1[x]){
if(ls)ad1(ls,t1[x]);
if(rs)ad1(rs,t1[x]);
}if(t2[x]){
if(ls)ad2(ls,t2[x]);
if(rs)ad2(rs,t2[x]);
}t1[x]=t2[x]=0;
}
void ppd(int x){
if(in(x))ppd(f[x]);pd(x);
}
void rot(int x){
int y=f[x],k=tp(x),w=t[x][!k];
t[f[w]=t[x][!k]=y][k]=w;
if(in(y))t[f[y]][tp(y)]=x;
f[x]=f[y],f[y]=x;
}
void splay(int x){ppd(x);
for(int y=f[x];in(x);rot(x),y=f[x])
if(in(y))rot(tp(x)^tp(y)?x:y);
}
void ins(int &x,int p){
if(!x){x=p;return;}
int k=v[p]>=v[x];pd(x);
ins(t[x][k],p),f[t[x][k]]=x;
}
void spt(int x,int &L,int &R,int k){//<=k to L
L=R=0;if(!x)return;
int mst=0;
while(1){pd(x);
if(v[x]<=k){
mst=x;
if(rs)x=rs;
else break;
}else if(ls)x=ls;
else break;
}splay(x);
if(mst){
x=mst,splay(x);
L=x,f[R=rs]=0,rs=0;
}else L=0,R=x;
}
void Add(int x){int k=Ik(v[x]);ins(rt[k],x),splay(x),rt[k]=x;}
void dfs(int x){
pd(x);
if(ls)dfs(ls);
if(rs)dfs(rs);
f[x]=ls=rs=0;
stk[++tp]=x;
}
void PPD(int x){
if(x){
pd(x);
if(ls)PPD(ls);
if(rs)PPD(rs);
}
}
void add1(int lm,int vl){
int l,r,k;tp=0;
for(k=1;k<=kt;++k)
if(R[k]>lm&&rt[k])
if(L[k]<=lm){
spt(rt[k],rt[k],r,lm);
ad1(r,lm),ad2(r,vl);
if(r)dfs(r);
}else{
ad1(rt[k],lm),ad2(rt[k],vl);
spt(rt[k],l,rt[k],L[k]-1);
if(l)dfs(l);
}
while(stk[tp])Add(stk[tp--]);
}
int mg(int x,int y){
if(!x||!y)return x|y;
while(rs)x=rs;
splay(x),f[rs=y]=x;return x;
}
void add2(int lm,int vl){
int l,r,k;
for(k=1;k<=kt;++k)
if(L[k]<lm&&rt[k])
if(R[k]>=lm){
spt(rt[k],l,r,lm-1);
// printf("l:%d r:%d\n",l,r);
// for(int x=1;x<=m;++x)
// if(sta[x])printf("x:%d v:%d w:%lld ls:%d rs:%d f:%d\n",x,v[x],w[x],ls,rs,f[x]);
if(l)ad2(l,vl);
rt[k]=mg(l,r);
}else ad2(rt[k],vl);
}
int main(){
ios::sync_with_stdio(false);
int i,j,k,l,r,x,y,lm,vl;
cin>>n>>m;
for(i=1;i<=n;++i)
cin>>d[i].l>>d[i].r>>d[i].v;
for(i=1;i<=m;++i){
cin>>l>>r>>v[i];
ad[l].push_back(i);
dl[r].push_back(i);
}
for(l=kt=0;l<=M;l=r+1){
r=min(3ll*(l+1),1ll*M),++kt;
L[kt]=l,R[kt]=r;
}
for(i=1;i<=n;++i){
for(int x:ad[i])Add(x),sta[x]=1;
if(d[i].r==-1)add1(d[i].l,d[i].v);
else add2(d[i].l,-d[i].v),add2(d[i].r+1,d[i].v);
for(int x:dl[i]){
splay(x);
f[ls]=f[rs]=0;
k=Ik(v[x]);
rt[k]=mg(ls,rs);
}
// PPD(rt[1]),PPD(rt[2]);
// exit(0);
}
for(i=1;i<=m;++i)
printf("%lld\n",w[i]);
return 0;
}