ARC047D
首杀问号题,虽然没有问号题的难度,但是至少是自己想出来的。
对于操作一和二,我们直接用分一个数组记录下来,
对于操作三,我们思考怎么样通过上面记录的信息处理答案。发现对于一个矩形,只要确定了
但是删除操作是比较难做的。我们先考虑不用删除的情况是什么,发现在矩形左上,右下角割出一个等腰直角三角形,这是可以直接做的,因为只会有加入。
然后考虑剩下的部分,发现这是一个平行四边形。放入刚才的思路中,这就变成了一个滑动窗口,直接单调队列维护即可。时间复杂度
细节还是不少的。首先要分成奇偶来讨论,其次单调队列部分要根据矩形形状决定加/删的是左端点还是右端点。处理答案可以像我一样,手写一个记录最大值和出现次数的 struct。
写得有点冗长,但是很多都是可以复制粘贴的,也不算很恶心,主要是样例强度足够。
code:
点击查看代码
int n,m,a[N],b[N];
struct node{
int x,y;
node(int _x=-inf,int _y=0){x=_x,y=_y;}
node operator+(const node &tmp)const{
node r=node(x,y);
if(tmp.x>r.x)r.x=tmp.x,r.y=tmp.y;
else if(tmp.x==r.x)r.y+=tmp.y;
return r;
}
};
struct Node{node x;int y;};
void Yorushika(){
scanf("%d%d",&n,&m);
if(n&1)n++;
rep(i,1,m){
int op,x,y,k;
scanf("%d%d%d",&op,&x,&y);
if(op==1){
scanf("%d",&k);
rep(j,x,y)a[j]+=k;
}else if(op==2){
scanf("%d",&k);
rep(j,x,y)b[j+n]+=k;
}else{
int X,Y;scanf("%d%d",&X,&Y);
x*=2,y*=2,X*=2,Y*=2;
int l[2]={-1,-1},r[2]={0,0},pl=n*2,pr=0;
node mx[2],ans;
rep(i,0,n*2){
int la=x-i,ra=y-i,lb=i-Y,rb=i-X,p=i&1;
int L=max(la,lb)+n,R=min(ra,rb)+n;
if(L>R)continue;
if(l[p]<0)for(int j=l[p]=L;j<=(r[p]=R);j+=2)mx[p]=mx[p]+node(b[j],1);
if(L>l[p]||R<r[p])break;
while(r[p]<R)r[p]+=2,mx[p]=mx[p]+node(b[r[p]],1);
while(l[p]>L)l[p]-=2,mx[p]=mx[p]+node(b[l[p]],1);
node tmp=mx[p];tmp.x+=a[i];
ans=ans+tmp,pl=i;
}
l[0]=l[1]=-1,r[0]=r[1]=0,mx[0]=mx[1]=node();
drep(i,n*2,pl+1){
int la=x-i,ra=y-i,lb=i-Y,rb=i-X,p=i&1;
int L=max(la,lb)+n,R=min(ra,rb)+n;
if(L>R)continue;
if(l[p]<0)for(int j=l[p]=L;j<=(r[p]=R);j+=2)mx[p]=mx[p]+node(b[j],1);
if(L>l[p]||R<r[p])break;
while(r[p]<R)r[p]+=2,mx[p]=mx[p]+node(b[r[p]],1);
while(l[p]>L)l[p]-=2,mx[p]=mx[p]+node(b[l[p]],1);
node tmp=mx[i&1];tmp.x+=a[i];
ans=ans+tmp,pr=i;
}
l[0]=l[1]=-1,r[0]=r[1]=0,mx[0]=mx[1]=node();
deque<node> q[2];
if(X-Y<=x-y){
rep(i,pl+1,pr-1){
int la=x-i,ra=y-i,lb=i-Y,rb=i-X,p=i&1;
int L=max(la,lb)+n,R=min(ra,rb)+n;
if(L>R)continue;
if(l[p]<0)for(int j=r[p]=R;j>=(l[p]=L);j-=2){
while(q[p].size()&&q[p].back().x<b[j])q[p].pop_back();
if(q[p].size()&&q[p].back().x==b[j]){
node tmp=q[p].back();
q[p].pop_back();
tmp.y++;
q[p].push_back(tmp);
}else q[p].push_back(node(b[j],1));
}else{
if(q[p].front().x==b[r[p]]){
node tmp=q[p].front();
q[p].pop_front();
tmp.y--;
if(tmp.y)q[p].push_front(tmp);
}
l[p]-=2,r[p]-=2;
while(q[p].size()&&q[p].back().x<b[l[p]])q[p].pop_back();
if(q[p].size()&&q[p].back().x==b[l[p]]){
node tmp=q[p].back();
q[p].pop_back();
tmp.y++;
q[p].push_back(tmp);
}else q[p].push_back(node(b[l[p]],1));
}
node tmp=q[p].front();tmp.x+=a[i];
ans=ans+tmp;
}
}else{
rep(i,pl+1,pr-1){
int la=x-i,ra=y-i,lb=i-Y,rb=i-X,p=i&1;
int L=max(la,lb)+n,R=min(ra,rb)+n;
if(L>R)continue;
if(l[p]<0)for(int j=l[p]=L;j<=(r[p]=R);j+=2){
while(q[p].size()&&q[p].back().x<b[j])q[p].pop_back();
if(q[p].size()&&q[p].back().x==b[j]){
node tmp=q[p].back();
q[p].pop_back();
tmp.y++;
q[p].push_back(tmp);
}else q[p].push_back(node(b[j],1));
}else{
if(q[p].front().x==b[l[p]]){
node tmp=q[p].front();
q[p].pop_front();
tmp.y--;
if(tmp.y)q[p].push_front(tmp);
}
l[p]+=2,r[p]+=2;
while(q[p].size()&&q[p].back().x<b[r[p]])q[p].pop_back();
if(q[p].size()&&q[p].back().x==b[r[p]]){
node tmp=q[p].back();
q[p].pop_back();
tmp.y++;
q[p].push_back(tmp);
}else q[p].push_back(node(b[r[p]],1));
}
node tmp=q[p].front();tmp.x+=a[i];
ans=ans+tmp;
}
}
printf("%d %d\n",ans.x,ans.y);
}
}
}
signed main(){
int t=1;
// scanf("%d",&t);
while(t--)
Yorushika();
}