Never gonna let you down
RedLycoris · · 题解
link
题目大意:
有一个
有
部分分:
题解:
我们考虑维护两个数组
对于一个点
关键在于这个询问。
我们可以枚举所有可能的
再继续考虑。
考虑特殊化,查询的是一个正方形。
如果我们从小到大枚举所有的
同理,我们再按照
再考虑把查询一般化为长方形,则可以按照类似辗转相减法的方法每次割出最大的正方形去查询,然后合并所有的答案,可以证明单次询问复杂度为
Code:
#include<bits/stdc++.h>
using namespace std;
const int mxn=1e4+9;
const int base=5003;
int n,q,s1[mxn],s2[mxn];
inline pair<int,int> G(pair<int,int> x,pair<int,int> y){
if(x.first!=y.first){
if(x.first>y.first)return x;
else return y;
}
x.second+=y.second;
return x;
}
inline pair<int,int> go(int a,int b,int c,int d){
int cur,cnt,len;
pair<int,int>rt={-1145141919,0};
cur=-1145141919,cnt=0,len=-2;
for(int sum1=a+b,sum2=c+d;sum1<=a+d;sum1+=2,sum2-=2){ //第一类
len+=2;
if(s2[a-b+base-len]>cur)cur=s2[a-b+base-len],cnt=1;
else if(s2[a-b+base-len]==cur)++cnt;
if(len!=0){
if(s2[a-b+base+len]>cur)cur=s2[a-b+base+len],cnt=1;
else if(s2[a-b+base+len]==cur)++cnt;
}
if(s1[sum1]+cur>rt.first){
rt.first=s1[sum1]+cur;
rt.second=cnt;
}else if(s1[sum1]+cur==rt.first){
rt.second+=cnt;
}
if(sum1!=sum2){
if(s1[sum2]+cur>rt.first){
rt.first=s1[sum2]+cur;
rt.second=cnt;
}else if(s1[sum2]+cur==rt.first){
rt.second+=cnt;
}
}
}
len=-1,cnt=0,cur=-1145141919;
for(int sum1=a+b+1,sum2=c+d-1;sum1<=a+d;sum1+=2,sum2-=2){ //第二类
len+=2;
if(s2[a-b+base-len]>cur)cur=s2[a-b+base-len],cnt=1;
else if(s2[a-b+base-len]==cur)++cnt;
if(len!=0){
if(s2[a-b+base+len]>cur)cur=s2[a-b+base+len],cnt=1;
else if(s2[a-b+base+len]==cur)++cnt;
}
if(s1[sum1]+cur>rt.first){
rt.first=s1[sum1]+cur;
rt.second=cnt;
}else if(s1[sum1]+cur==rt.first){
rt.second+=cnt;
}
if(sum1!=sum2){
if(s1[sum2]+cur>rt.first){
rt.first=s1[sum2]+cur;
rt.second=cnt;
}else if(s1[sum2]+cur==rt.first){
rt.second+=cnt;
}
}
}
return rt;
}
inline auto solve(int a,int b,int c,int d){//割成极大正方形
if(c-a==d-b)return go(a,b,c,d);
int l=min(c-a,d-b);
if(c-a>d-b){
pair<int,int> rt=go(a,b,a+l,b+l);
rt=G(rt,solve(a+l+1,b,c,d));
return rt;
}else{
pair<int,int> rt=go(a,b,a+l,b+l);
rt=G(rt,solve(a,b+l+1,c,d));
return rt;
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>q;
for(;q--;){
int tp,a,b,c,d;
cin>>tp;
if(tp==1){
cin>>a>>b>>c;
for(int i=a;i<=b;++i)s1[i]+=c;
}
if(tp==2){
cin>>a>>b>>c;
a+=base,b+=base;
for(int i=a;i<=b;++i)s2[i]+=c;
}
if(tp==3){
cin>>a>>b>>c>>d;
auto p=solve(a,c,b,d);
cout<<p.first<<' '<<p.second<<'\n';
}
}
}