P9388 [THUPC 2023 决赛] 先人类的人类选别
Description
https://www.luogu.com.cn/problem/P9388
Solution
观察到操作序列一定,操作顺序对答案并没有影响。
将答案拆为
观察到对于一个前缀区间,操作的本质就是将当前操作的所有
没有卡常。
#define int long long
#define maxn 500005
int n,m;
int a[maxn],suf[maxn],root[maxn],rota,cnt;
struct node {
int ls,rs,sum,siz;
} f[maxn*30];
int Update(int l,int r,int pre,int head) {
int rt=++cnt;
f[rt]=f[pre];
f[rt].siz++;
f[rt].sum+=head;
if (l==r) return rt;
int mid=l+r>>1;
if (head<=mid) f[rt].ls=Update(l,mid,f[rt].ls,head);
else f[rt].rs=Update(mid+1,r,f[rt].rs,head);
return rt;
}
void Update2(int l,int r,int &rt,int head) {
if (!rt) rt=++cnt;
f[rt].siz++,f[rt].sum+=head;
if (l==r) return ;
int mid=l+r>>1;
if (head<=mid) Update2(l,mid,f[rt].ls,head);
else Update2(mid+1,r,f[rt].rs,head);
}
int Query(int l,int r,int rt1,int rt2,int k) {
if (l==r) return k*l;
int mid=l+r>>1,siz=f[f[rt1].ls].siz+f[f[rt2].ls].siz;
if (siz>=k) return Query(l,mid,f[rt1].ls,f[rt2].ls,k);
else return f[f[rt1].ls].sum+f[f[rt2].ls].sum+Query(mid+1,r,f[rt1].rs,f[rt2].rs,k-siz);
}
signed main(void) {
int i,x,l,r,sum=0;
read(n);
read(m);
for (i=1; i<=n; i++) read(a[i]),suf[i]=suf[i-1]+a[i];
for (i=1; i<=n; i++) {
root[i]=Update(1,n,root[i-1],a[i]);
}
for (i=1; i<=m; i++) {
read(x);read(l);read(r);sum+=x;
Update2(1,n,rota,x);
int tmp1=suf[l-1]+sum-Query(1,n,root[l-1],rota,i);
int tmp2=suf[r]+sum-Query(1,n,root[r],rota,i);
printf("%lld\n",tmp2-tmp1);
}
return 0;
}