『Raiden Ei』 Round 1千手百眼,天下人间题解
题目背景

影小姐在创作小说《转生成为八重宫司,然后天下无敌》。
但是由于神子不定时会过来贴贴,所以她不得不在神子来到时对所写的文稿进行掩饰甚至撤销,所以导致整个写作过程乱七八糟。
现在她很生气,请你在她生气的拔刀斩了你之前回答她的所有问题。
题目描述
我们将提瓦特文抽象成正整数数字。
初始时影有序列 A 作为草稿,长度为 n。
但是写着写着,她心情总是飘忽不定的变化,所以草稿也会随之变化。
有以下三种可能的事件:
- 在第 ti 时刻,将 li 到 ri 的所有值增加 ki。
- 在第 ti 时刻,查询区间 li 到 ri 之间所有数的最大值。
- 在第 ti 时刻,将 li 到 ri 这些时间点发生的三种事件全部撤销。
在影写完冷静下来之后,请你对于所有未被撤销的查询进行回答。
输入格式
第一行输入两个正整数 n,m。
第二行输入 n 个整数,表示序列 A。
接下来 m 行,每行输入第一个元素 opt 作为操作类型。
-
若 opt=1,则按顺序输入 ti,li,ri,ki,表示一次修改,满足 −109≤ki≤109。
-
若 opt=2,则按顺序输入 ti,li,ri,表示一次查询。
-
若 opt=3,则按顺序输入 ti,li,ri,表示一次撤销,满足 li≤ri<ti。
输出格式
第一行输出一个整数 cnt,表示有效的查询次数。
接下来 cnt 行,每行一个整数作为答案。
注意:你所输出的答案应按照时间顺序,若两个查询时间相同,则优先回答操作编号较小的那次查询,同理,两个操作时间相同时优先执行编号小的操作。
输入输出样例
输入 #1复制
3 5 0 0 0 1 1 1 3 5 2 2 1 3 3 3 1 1 2 4 1 3 1 5 1 1 10
输出 #1复制
2 0 0
输入 #2复制
3 4 1 2 3 1 1 1 3 5 2 2 1 3 3 3 2 2 2 4 1 3
输出 #2复制
1 8
说明/提示
对于前 10% 的数据,满足 n,m≤10。
对于另 20% 的数据,满足不含有撤销操作。
对于另 10% 的数据,满足没有修改操作。
对于 100% 的数据,满足 1≤n,m≤5×105,−109≤Ai≤109,1≤ti≤1018。
思路
看到区间操作,考虑线段树,然后从后向前扫,去除删除项即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
// map<long long,long long> mp;
int opt[500005],n,m,a[500005],k[500005];
int te[4000006];
int lz[4000006];
int df=0;
int cf[1500006],cf2[1500006];
struct one{
int opt,k,i;
long long t,l,r;
}aa[500005];
bool cmp2(one a1,one b1){
if(a1.t!=b1.t){
return a1.t<b1.t;
}
else{
return a1.i<b1.i;
}
}
void alz(int a1,int v){
te[a1]+=v;
lz[a1]+=v;
}//a1打标记值v
void dow(int a1){
alz(a1*2,lz[a1]);
alz(a1*2+1,lz[a1]);
lz[a1]=0;
}//a1下发标记至儿子
void bu(int a1,int l,int r){
if(l==r){
te[a1]=a[l];
return ;
}
int mid=(l+r)/2;
bu(a1*2,l,mid);
bu(a1*2+1,mid+1,r);
te[a1]=max(te[a1*2],te[a1*2+1]);
return ;
}//l~r建树节点a1
void ci(int a1,int l,int r,int x,int y,int v){
if(l>=x&&r<=y){
alz(a1,v);
return ;
}
int mid=(l+r)/2;
dow(a1);
if(x<=mid){
ci(a1*2,l,mid,x,y,v);
}
if(mid+1<=y){
ci(a1*2+1,mid+1,r,x,y,v);
}
te[a1]=max(te[a1*2],te[a1*2+1]);
return ;
}//x~y区间加v至l~r区间a1点
long long co(int a1,int l,int r,int x,int y){
if(x<=l&&r<=y){
return te[a1];
}
int mid=(l+r)/2;
long long dbdb=-1e18-7;
dow(a1);
if(mid>=x){
dbdb=max(dbdb,co(a1*2,l,mid,x,y));
}
if(mid+1<=y){
dbdb=max(dbdb,co(a1*2+1,mid+1,r,x,y));
}
te[a1]=max(te[a1*2],te[a1*2+1]);
return dbdb;
}//x~y区间问至l~r区间a1点
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
bu(1,1,n);
for(int i=1;i<=m;i++){
cin>>aa[i].opt;
aa[i].i=i;
if(aa[i].opt==1){
cin>>aa[i].t>>aa[i].l>>aa[i].r>>aa[i].k;
//lp[++lp[0]]=aa[i].t;
}
else if(aa[i].opt==2){
cin>>aa[i].t>>aa[i].l>>aa[i].r;
df++;
//lp[++lp[0]]=aa[i].t;
}
else{
cin>>aa[i].t>>aa[i].l>>aa[i].r;
//lp[++lp[0]]=aa[i].t;
//lp[++lp[0]]=aa[i].l;
//lp[++lp[0]]=aa[i].r;
}
}
// sort(lp+1,lp+lp[0]+1);
// for(int i=1;i<=lp[0];i++){
// mp[lp[i]]=i;
// }
// for(int i=1;i<=m;i++){
// if(aa[i].opt==1){
// aa[i].t=mp[aa[i].t];
// }
// else if(aa[i].opt==2){
// aa[i].t=mp[aa[i].t];
// }
// else{
// aa[i].t=mp[aa[i].t];
// aa[i].l=mp[aa[i].l];
// aa[i].r=mp[aa[i].r];
// }
// }
sort(aa+1,aa+m+1,cmp2);
df=0;
for(int i=m;i>=1;i--){
cf2[i]=cf2[i+1]+cf[i];
if(aa[i].opt==3&&cf2[i]<=0&&i!=1){
long long l=1,r=i-1,md=i;
while(l<=r){
long long mid=(l+r)/2;
if(aa[mid].t>=aa[i].l){
md=min(md,mid);
r=mid-1;
}
else{
l=mid+1;
}
}
l=1;
r=i-1;
long long md2=0;
while(l<=r){
long long mid=(l+r)/2;
if(aa[mid].t<=aa[i].r){
md2=max(md2,mid);
l=mid+1;
}
else{
r=mid-1;
}
}
if(md<=md2){
cf[md2]++;
cf[md-1]--;
}
}
else if(aa[i].opt==2&&cf2[i]<=0){
df++;
}
}
//sort(aa+1,aa+m+1,cmp2);
cout<<df<<endl;
for(int i=1;i<=m;i++){
if(aa[i].opt==1&&cf2[i]<=0){
ci(1,1,n,aa[i].l,aa[i].r,aa[i].k);
}
else if(aa[i].opt==2&&cf2[i]<=0){
cout<<co(1,1,n,aa[i].l,aa[i].r)<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号