其他分享
首页 > 其他分享> > 2022南外集训 Day2

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