题解:CF2006D Iris and Adjacent Products
IvanZhang2009 · · 题解
这个题初始的 idea 是 irris 的(关于“可以重排使得邻项积不超过
这个题卡空间是因为开二维数组常数太大了,做法几乎不变的同时,隐形强制要求小常数避免卡常。当然莫队可以直接解决。
题意:对于一个序列,你可以做单点修改(任何时刻值域都是
解法:考虑最优的重排方式,先放最大值,然后最小值,然后次大值等等地交替放。于是序列合法当且仅当每个
上述结论的证明:
先证明最大值放第一个更优。如果存在一个同样可行的方法最大值不在第一个,我们可以把以最大值结尾的这个前缀 reverse,直接达成不劣的效果。
再考虑最小值放第二个更优。如果存在一个同样可行的解最小值不在第二个,我们考虑当前的第二个和最小值,由于都可以放在 max 旁边,所以对于所有数都可以放它们旁边,是等价的。于是交换这两个数结果不变。
所有数都可以放到最小值旁边,于是变成
n'=n-2 的子问题,于是得证。
设
考虑卡空间,由于各
#include<bits/stdc++.h>
using namespace std;
#define MOD 998244353
#define speMOD 2933256077ll
#define pii pair<int,int>
#define all(v) v.begin(),v.end()
#define pb push_back
#define REP(i,b,e) for(int i=(b);i<(int)(e);++i)
#define over(x) {cout<<(x)<<endl;return;}
#define lowbit(x) ((x)&(-(x)))
#define cntbit(x) __builtin_popcount(x)
#define rf(v) shuffle(all(v),sd);
#define deal(v) sort(all(v));v.erase(unique(v.begin(),v.end()),v.end())
#define lbound(v,x) lower_bound(all(v),x)-v.begin()
int n,q,r;
int a[300005];
int sum[300005];
int ql[300005],qr[300005];
int ans[300005];
int cnt[300005],cnt2[300005];
void Main() {
cin>>n>>q>>r;
REP(i,0,n)cin>>a[i];
sum[0]=0;
int B=sqrt(r);
REP(i,0,n)sum[i+1]=sum[i]+(a[i]<=B);
REP(i,0,q){
int x,y;
cin>>x>>y;
--x,--y;
ql[i]=x;qr[i]=y;
ans[i]=0;
if(sum[y+1]-sum[x]<(y-x+1)/2)ans[i]=(y-x+1)/2-sum[y+1]+sum[x];
}
REP(i,0,B){
REP(j,0,n+1)cnt[j]=cnt2[j]=0;
REP(j,0,n){
cnt[j+1]=cnt[j]+(a[j]<=i);
cnt2[j+1]=cnt2[j]+(a[j]<=r/(i+1));
}
REP(j,0,q){
int x=ql[j],y=qr[j],l=y-x+1;
int c1=cnt2[y+1]-cnt2[x],c2=cnt[y+1]-cnt[x];
ans[j]=max(ans[j],min((l-c1-c2+1)/2,l/2-c2));
}
}
REP(i,0,q)cout<<ans[i]<<' ';
cout<<endl;
}
void TC() {
int tc=1;
cin>>tc;
while(tc--){
Main();
cout.flush();
}
}
signed main() {
return cin.tie(0),cout.tie(0),ios::sync_with_stdio(0),TC(),0;
}
/*
1. CLEAR the arrays (ESPECIALLY multitests)
2. DELETE useless output
*/