2022南外集训 Day2
作者:互联网
杂言
今天分块专场,感觉前几题很基础,就是细节太多
(卡常差评
T1 单点修改 区间查询
大力分块 (你只管大力)
T1 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,val[maxn],m;
char s[10];
int block,bel[maxn];
int sum[maxn];
signed main()
{
n=read(); m=read();
for(int i=1;i<=n;i++) val[i]=read();
block=(int)sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/block+1;
int len=bel[n];
for(int i=1;i<=len;i++)
{
int l=(i-1)*block+1,r=i*block;
for(int j=l;j<=r;j++) sum[i]+=val[j];
}
while(m--)
{
int x,y,ans(0);
scanf("%s",s+1);
x=read(); y=read();
if(s[1]=='Q')
{
if(bel[x]==bel[y])
{
for(int i=x;i<=y;i++) ans+=val[i];
printf("%lld\n",ans);
continue;
}
for(int i=x;i<=bel[x]*block;i++) ans+=val[i];
for(int i=(bel[y]-1)*block+1;i<=y;i++) ans+=val[i];
for(int i=bel[x]+1;i<=bel[y]-1;i++) ans+=sum[i];
printf("%lld\n",ans);
}
else sum[bel[x]]+=y-val[x],val[x]=y;
}
return 0;
}
T2 区间加法 单点查询
没啥可说
T2 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,val[maxn],m;
char s[10];
int block,bel[maxn];
int tag[maxn];
signed main()
{
n=read();
for(int i=1;i<=n;i++) val[i]=read();
block=(int)sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/block+1;
while(n--)
{
int x,y,ans(0),opt,c;
opt=read();
x=read(); y=read(); c=read();
if(!opt)
{
if(bel[x]==bel[y])
{for(int i=x;i<=y;i++) val[i]+=c; continue;}
for(int i=x;i<=bel[x]*block;i++) val[i]+=c;
for(int i=(bel[y]-1)*block+1;i<=y;i++) val[i]+=c;
for(int i=bel[x]+1;i<=bel[y]-1;i++) tag[i]+=c;
}
else printf("%lld\n",val[y]+tag[bel[y]]);
}
return 0;
}
T3 区间加法 求x前驱
就是小于x最大的那个,我们直接对每个块里面的东西排序,左右分块可以暴力,中间二分即可
T3 O2 accept
#pragma GCC optimize(2)
#define FASTER
#ifdef FASTER
#pragma GCC diagnostic error "-std=c++11"
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#endif
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
const int inf=0x80000000;
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,val[maxn];
int block,bel[maxn];
int tag[1005],ans(0);
vector<int> b[1005];
signed main()
{
n=read();
for(int i=1;i<=n;i++) val[i]=read();
block=pow(n,(double)2/(double)3);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/block+1,b[bel[i]].push_back(val[i]);
int len=bel[n];
for(int i=1;i<=len;i++)
sort(b[i].begin(),b[i].end());
int p=0;
for(int k=1;k<=n;k++)
{
int x,y,opt,c;
opt=read();
x=read(); y=read(); c=read();
if(!opt)
{
if(bel[x]==bel[y])
{
p=bel[x];
b[p].clear();
for(int i=x;i<=y;i++) val[i]+=c;
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
b[p].push_back(val[i]);
sort(b[p].begin(),b[p].end());
continue;
}
p=bel[x];
for(int i=x;i<=bel[x]*block;i++) val[i]+=c;
b[p].clear();
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
b[p].push_back(val[i]);
sort(b[p].begin(),b[p].end());
p=bel[y];
for(int i=(bel[y]-1)*block+1;i<=y;i++) val[i]+=c;
b[p].clear();
for(int i=(bel[y]-1)*block+1;i<=min(n,bel[y]*block);i++)
b[p].push_back(val[i]);
sort(b[p].begin(),b[p].end());
for(int i=bel[x]+1;i<=bel[y]-1;i++) tag[i]+=c;
}
else
{
ans=-1;
if(bel[x]==bel[y])
{
for(int i=x;i<=y;i++)
if(val[i]+tag[bel[x]]<c) ans=max(ans,val[i]+tag[bel[x]]);
printf("%lld\n",ans); continue;
}
for(int i=x;i<=bel[x]*block;i++)
if(val[i]+tag[bel[i]]<c) ans=max(ans,val[i]+tag[bel[i]]);
for(int i=(bel[y]-1)*block+1;i<=y;i++)
if(val[i]+tag[bel[i]]<c) ans=max(ans,val[i]+tag[bel[i]]);
for(int i=bel[x]+1;i<=bel[y]-1;i++)
{
int tmp=lower_bound(b[i].begin(),b[i].end(),c-tag[i])-b[i].begin();
if(tmp) ans=max(ans,b[i][tmp-1]+tag[i]);
}
printf("%lld\n",ans);
}
}
return 0;
}
T4 区间加法 询问区间内小于x的个数
跟上面一样,也需要二分位置
T4 O2 accept
#pragma GCC optimize(2)
#define FASTER
#ifdef FASTER
#pragma GCC diagnostic error "-std=c++11"
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#endif
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=5e4+5;
const int inf=0x80000000;
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,val[maxn];
int block,bel[maxn];
int tag[1005],ans(0);
vector<int> b[1005];
signed main()
{
n=read();
for(int i=1;i<=n;i++) val[i]=read();
block=sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/block+1,b[bel[i]].push_back(val[i]);
int len=bel[n];
for(int i=1;i<=len;i++)
sort(b[i].begin(),b[i].end());
int p=0;
for(int k=1;k<=n;k++)
{
int x,y,opt,c;
opt=read();
x=read(); y=read(); c=read();
if(!opt)
{
if(bel[x]==bel[y])
{
p=bel[x];
b[p].clear();
for(int i=x;i<=y;i++) val[i]+=c;
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
b[p].push_back(val[i]);
sort(b[p].begin(),b[p].end());
continue;
}
p=bel[x];
for(int i=x;i<=bel[x]*block;i++) val[i]+=c;
b[p].clear();
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
b[p].push_back(val[i]);
sort(b[p].begin(),b[p].end());
p=bel[y];
for(int i=(bel[y]-1)*block+1;i<=y;i++) val[i]+=c;
b[p].clear();
for(int i=(bel[y]-1)*block+1;i<=min(n,bel[y]*block);i++)
b[p].push_back(val[i]);
sort(b[p].begin(),b[p].end());
for(int i=bel[x]+1;i<=bel[y]-1;i++) tag[i]+=c;
}
else
{
ans=0;
if(bel[x]==bel[y])
{
for(int i=x;i<=y;i++)
if(val[i]+tag[bel[x]]<c*c) ans++;
printf("%lld\n",ans); continue;
}
for(int i=x;i<=bel[x]*block;i++)
if(val[i]+tag[bel[i]]<c*c) ans++;
for(int i=(bel[y]-1)*block+1;i<=y;i++)
if(val[i]+tag[bel[i]]<c*c) ans++;
for(int i=bel[x]+1;i<=bel[y]-1;i++)
{
int tmp=lower_bound(b[i].begin(),b[i].end(),c*c-tag[i])-b[i].begin();
ans+=tmp;
}
printf("%lld\n",ans);
}
}
return 0;
}
T5 区间修改 区间查询
这个处理的问题就是需要考虑每次不整的块对当前块\(sum\)值的影响
T5 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=5e4+5;
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,val[maxn];
int block,bel[maxn];
int sum[maxn],tag[maxn];
signed main()
{
n=read();
for(int i=1;i<=n;i++) val[i]=read();
block=(ll)sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/block+1;
int len=bel[n];
for(int i=1;i<=len;i++)
{
tag[i]=0;
int l=(i-1)*block+1,r=i*block;
for(int j=l;j<=r;j++) sum[i]+=val[j];
}
for(int k=1;k<=n;k++)
{
int x,y,ans=0,opt,c;
opt=read();
x=read(); y=read(); c=read();
if(x>y) swap(x,y);
if(!opt)
{
if(bel[x]==bel[y])
{
for(int i=x;i<=y;i++) val[i]+=c;
sum[bel[x]]+=(y-x+1)*c;
continue;
}
for(int i=x;i<=bel[x]*block;i++) val[i]+=c;
sum[bel[x]]+=(bel[x]*block-x+1)*c;
for(int i=(bel[y]-1)*block+1;i<=y;i++) val[i]+=c;
sum[bel[y]]+=(y-(bel[y]-1)*block)*c;
for(int i=bel[x]+1;i<=bel[y]-1;i++)
tag[i]+=c,sum[i]+=block*c;
}
else
{
if(bel[x]==bel[y])
{for(int i=x;i<=y;i++) ans=(ans+val[i]+tag[bel[i]])%(c+1);
printf("%lld\n",ans%(c+1)); continue;}
for(int i=x;i<=bel[x]*block;i++) ans=(ans+tag[bel[i]]+val[i])%(c+1);
for(int i=(bel[y]-1)*block+1;i<=y;i++) ans=(ans+tag[bel[i]]+val[i])%(c+1);
for(int i=bel[x]+1;i<=bel[y]-1;i++) ans=(ans+sum[i])%(c+1);
printf("%lld\n",ans%(c+1));
}
}
return 0;
}
/*4
1 1 1 1
0 1 3 2
0 2 3 1
0 3 4 9
1 1 4 10*/
T6 区间开方 区间求和
和线段树那里写的一样,int开方只会开最多5次
5次 \(O(n\cdot log n)\)
T6 segtree accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
#define lc(x) x<<1
#define rc(x) x<<1|1
#define mx(x) tree[x].mx
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,a[maxn],m;
struct node
{
ll sum,mx;
}tree[maxn<<2];
void push_up(int id)
{
tree[id].sum=tree[lc(id)].sum+tree[rc(id)].sum;
mx(id)=max(mx(lc(id)),mx(rc(id)));
return ;
}
void build(int id,int l,int r)
{
if(l==r)
{tree[id].mx=tree[id].sum=a[l]; return ;}
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
return ;
}
void modify(int id,int l,int r,int x,int y)
{
if(mx(id)==1||mx(id)==0) return ;
if(l==r)
{
tree[id].sum=(ll)floor(sqrt(tree[id].mx));
tree[id].mx=tree[id].sum;
return ;
}
int mid=(l+r)>>1;
if(x<=mid) modify(lc(id),l,mid,x,y);
if(y>mid) modify(rc(id),mid+1,r,x,y);
push_up(id);
return ;
}
int query(int id,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return tree[id].sum;
int mid=(l+r)>>1;
ll ans=0;
if(x<=mid) ans+=query(lc(id),l,mid,x,y);
if(y>mid) ans+=query(rc(id),mid+1,r,x,y);
return ans;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
for(int p=1;p<=n;p++)
{
int x,l,r,c;
x=read(); l=read(); r=read(); c=read();
if(x==0) modify(1,1,n,l,r);
else printf("%lld\n",query(1,1,n,l,r));
}
return 0;
}
T7
T8 区间乘法加法 单点查询
和线段树思路一样,优先考虑乘法,再考虑加法
T8 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e6+5;
const int inf=0x80000000;
const int mod=1e4+7;
#define int long long
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int n,val[maxn];
int block,bel[maxn];
int tag[1005],mul[1005],ans(0);
signed main()
{
n=read();
for(int i=1;i<=n;i++) val[i]=read()%mod;
block=sqrt(n);
for(int i=1;i<=n;i++)
bel[i]=(i-1)/block+1;
int len=bel[n];
for(int i=1;i<=len;i++) mul[i]=1;
for(int k=1;k<=n;k++)
{
int x,y,opt,c;
opt=read();
x=read(); y=read(); c=read();
if(opt==0)
{
if(bel[x]==bel[y])
{
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
val[i]=(val[i]*mul[bel[x]])%mod,val[i]=(val[i]+tag[bel[x]])%mod;
for(int i=x;i<=y;i++) val[i]=(val[i]+c)%mod;
tag[bel[x]]=0; mul[bel[x]]=1;
continue;
}
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
val[i]=(val[i]*mul[bel[x]])%mod,val[i]=(val[i]+tag[bel[x]])%mod;
for(int i=x;i<=bel[x]*block;i++) val[i]=(val[i]+c)%mod;
tag[bel[x]]=0; mul[bel[x]]=1;
for(int i=(bel[y]-1)*block+1;i<=bel[y]*block;i++)
val[i]=(val[i]*mul[bel[y]])%mod,val[i]=(val[i]+tag[bel[y]])%mod;
for(int i=(bel[y]-1)*block+1;i<=y;i++) val[i]=(val[i]+c)%mod;
tag[bel[y]]=0; mul[bel[y]]=1;
for(int i=bel[x]+1;i<=bel[y]-1;i++) tag[i]=(tag[i]+c)%mod;
}
else if(opt==1)
{
if(bel[x]==bel[y])
{
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
val[i]=(val[i]*mul[bel[x]])%mod,val[i]=(val[i]+tag[bel[x]])%mod;
for(int i=x;i<=y;i++) val[i]=(val[i]*c)%mod;
tag[bel[x]]=0; mul[bel[x]]=1;
continue;
}
for(int i=(bel[x]-1)*block+1;i<=bel[x]*block;i++)
val[i]=(val[i]*mul[bel[x]])%mod,val[i]=(val[i]+tag[bel[x]])%mod;
for(int i=x;i<=bel[x]*block;i++) val[i]=(val[i]*c)%mod;
tag[bel[x]]=0; mul[bel[x]]=1;
for(int i=(bel[y]-1)*block+1;i<=bel[y]*block;i++)
val[i]=(val[i]*mul[bel[y]])%mod,val[i]=(val[i]+tag[bel[y]])%mod;
for(int i=(bel[y]-1)*block+1;i<=y;i++) val[i]=(val[i]*c)%mod;
tag[bel[y]]=0; mul[bel[y]]=1;
for(int i=bel[x]+1;i<=bel[y]-1;i++) mul[i]=(mul[i]*c)%mod,tag[i]=(tag[i]*c)%mod;
}
else printf("%lld\n",(val[y]*mul[bel[y]]%mod+tag[bel[y]])%mod);
}
return 0;
}
T9
T10 区间最小众数
原题链接:Luogu P4168 [Violet]蒲公英
原题强制在线,其实强不强制都一样
因为是众数,没法主席树,考虑大力分块
每次我们需要维护一个东西,就是区间内整块中的众数以及其出现次数
考虑小dp
预处理出两个数组:
\(p[i][j]\):表示第\(i\)个块 到第\(j\)个块的(最小的)众数。
\(s[i][j]\):类似于前缀和,在前\(i\)个(包括 \(i\) )个块中\(j\)(离散化之后的值)出现了几次
考虑怎么处理,\(s\)数组我们每一次先继承\(s[i-1][j]\),然后在当前块\(i\)中直接扫
复杂度是:\(O(n \sqrt n)\)
而\(p[i][j]\),我们可以枚举\(i,j\)块,然后枚举块\(j\),我们知道\(p[i][j-1]\),那么就可以利用它去更新\(p[i][j]\)
复杂度是:\(O(\sqrt n \cdot \sqrt n \cdot \sqrt n)=O(n \sqrt n)\)
那么,处理完这些,我们可以对于不整的块(左端和右端),进行暴力
细节很多,还得仔细
T10 accept
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<string>
#include<cstdlib>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5;
const int maxm=355;
inline int read()
{
int x=0,y=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') y=-1; c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
int block,n,m;
int b[maxn],col[maxn];
int len(0),cnt(0);
int get(int pos) {return (pos-1)/block+1;}
int sum[maxm][maxn];
int f[maxm][maxm],t[maxn];
int main()
{
n=read();
block=(int)sqrt(n);
for(int i=1;i<=n;i++) b[i]=col[i]=read();
sort(b+1,b+1+n);
len=unique(b+1,b+1+n)-b-1;
cnt=(n-1)/block+1;
for(int i=1;i<=n;i++)
col[i]=lower_bound(b+1,b+1+len,col[i])-b;
for(int i=1;i<=cnt;i++)
{
for(int j=block*(i-1)+1;j<=min(block*i,n);j++)
sum[i][col[j]]++;
for(int j=1;j<=len;j++)
sum[i][j]+=sum[i-1][j];
}
for(int i=1;i<=cnt;i++)
{
for(int j=i;j<=cnt;j++)
{
int mx=f[i][j-1];
for(int k=block*(j-1);k<=min(block*j,n);k++)
if(sum[j][col[k]]-sum[i-1][col[k]]>sum[j][mx]-sum[i-1][mx]||(
(sum[j][col[k]]-sum[i-1][col[k]]==sum[j][mx]-sum[i-1][mx])&&col[k]<mx))
mx=col[k];
f[i][j]=mx;
}
}
for(int ppp=1;ppp<=n;ppp++)
{
int l=read(),r=read();
int bl=get(l),br=get(r),mx=0;
if(br-bl<=1)
{
for(int i=l;i<=r;i++) t[col[i]]++;
for(int i=l;i<=r;i++)
if(t[col[i]]>t[mx]||(t[col[i]]==t[mx]&&col[i]<mx))
mx=col[i];
for(int i=l;i<=r;i++) t[col[i]]=0;
printf("%d\n",b[mx]);
continue;
}
for(int i=l;i<=block*bl;i++) t[col[i]]++;
for(int i=block*(br-1)+1;i<=r;i++) t[col[i]]++;
mx=f[bl+1][br-1];
for(int i=l;i<=block*bl;i++)
{
int pre=t[mx]+sum[br-1][mx]-sum[bl][mx];
int u= t[col[i]]+sum[br-1][col[i]]-sum[bl][col[i]];
if(u>pre||(u==pre&&mx>col[i])) mx=col[i];
}
for(int i=block*(br-1)+1;i<=r;i++)
{
int pre=t[mx]+sum[br-1][mx]-sum[bl][mx];
int u=t[col[i]]+sum[br-1][col[i]]-sum[bl][col[i]];
if(u>pre||(u==pre&&mx>col[i])) mx=col[i];
}
for(int i=l;i<=block*bl;i++) t[col[i]]=0;
for(int i=block*(br-1)+1;i<=r;i++) t[col[i]]=0;
printf("%d\n",b[mx]);
}
return 0;
}
标签:GCC,2022,int,Day2,long,南外,pragma,include,optimize 来源: https://www.cnblogs.com/mastey/p/16448514.html