社区讨论

警示后人&&提问

P4168[Violet] 蒲公英参与者 3已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@lo85qgje
此快照首次捕获于
2023/10/27 13:13
2 年前
此快照最后确认于
2023/10/27 13:13
2 年前
查看原帖
看着蓝书写的(就是李煜东的《算法竞赛进阶指南》)
将块数T和长度len设置为书上写的
CPP
T=sqrt(n*(log(n)/log(2)));
len=n/T;
WA0分
设置为
CPP
T=sqrt(n);
len=n/T;
A了
如果可能是我代码的问题,在此附上代码
CPP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string.h>
#include <cmath>
#define rep(a,b,c) for(register int a=b;a<=c;++a)
using namespace std;
int T,n,m;
typedef long long ll;
const int N=40001;
int len;
//快读------------------------------------------ 
inline char gc() {
	static char BB[1000000],*S=BB,*T=BB;
	return S==T&&(T=(S=BB)+fread(BB,1,1000000,stdin),S==T)?EOF:*S++;
}
inline int read() {
	int x=0,f=1;
	char ch=gc();
	while(ch<'0'||ch>'9') {
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-48;
		ch=gc();
	}
	return x*f;
}
//---------------------------------------------- 
vector<int> dic;
vector<int> d[N];
int p[1001][1001];
int a[N];
void init() {
	n=read();
	m=read();
	//T=sqrt(n*(log(n)/log(2)));
	//len=n/T;
	T=sqrt(n);
	len=n/T;
	rep(i,1,n) {
		a[i]=read();
		dic.push_back(a[i]);
	}
	//-------------------------------------------------离散化
	sort(dic.begin(),dic.end());
	int tot=unique(dic.begin(),dic.end())-dic.begin();
	rep(i,1,n) a[i]=lower_bound(dic.begin(),dic.begin()+tot,a[i])-dic.begin()+1;
	//-------------------------------------------------------
	rep(i,1,n) d[a[i]].push_back(i);//为num()查询构建d数组,记录每一种蒲公英的出现位置 
	int v[N];//桶 
	//-----------------------------------预处理块间众数
	rep(i,1,T) {
		memset(v,0,sizeof v);
		int mmax[2]= {0,0};
		rep(j,i,T) {
			int r=j*len,l=r-len+1;
			rep(k,l,r) {
				v[a[k]]++;
				if(v[a[k]]>mmax[0]||(v[a[k]]==mmax[0]&&a[k]<mmax[1])) {//取编号最小 
					mmax[0]=v[a[k]],mmax[1]=a[k];
				}
			}
			p[i][j]=mmax[1];//p[i][j]记录第i块到第j块(左闭右闭)众数 
		}
	}
	//--------------------------------------------------
}
inline int num(int k,int l,int r) {//求区间k类蒲公英的数量 
	int up=upper_bound(d[k].begin(),d[k].end(),r)-d[k].begin()-1;
	int down=lower_bound(d[k].begin(),d[k].end(),l)-d[k].begin();
	return up-down+1;
}
int query(int l,int r) {
	int L=ceil(l*1.0/len)+1,R=ceil(r*1.0/len)-1;//区间内可用块的区间
	int now=num(p[L][R],l,r),ret=p[L][R];
	rep(i,l,(L-1)*len) {//trival左边 
		int cnt=num(a[i],l,r);
		if(cnt>now||(cnt==now&&a[i]<ret)) {//注意取编号最小 
			now=cnt;
			ret=a[i];
		}
	}
	rep(i,(R*len)+1,r) {//trival右边 
		int cnt=num(a[i],l,r);
		if(cnt>now||(cnt==now&&a[i]<ret)) {//注意取编号最小 
			now=cnt;
			ret=a[i];
		}
	}
	return ret;
}
int main() {
	//freopen("in.in","r",stdin);
	//freopen("P4168_1.in","r",stdin);
	//freopen("out.out","w",stdout);
	init();
	ll l,r,lasans=0;
	rep(i,1,T) {
//		rep(j,i,T) cout<<(i-1)*len+1<<" "<<j*len<<" "<<p[i][j]<<"\n";
	}
	rep(k,1,m) {
		l=read(),r=read();
		l=(l+lasans-1)%n+1;
		r=(r+lasans-1)%n+1;
		if(l>r) swap(l,r);
		lasans=dic[query(l,r)-1];//还原,注意-1 
		cout<<lasans<<endl;
	}
	return 0;
}

回复

7 条回复,欢迎继续交流。

正在加载回复...