CF1181D Irrigation

经简单分析可知

若是 (n = 0),那么以后的比赛将会有周期性:(1,2,3,dots,m)

进一步来说,一定存在某个值使得,当 k 高于这个值的时候将会呈现于 m 有关的周期性。仔细分析之后可知,这个值为 (h imes m - n)

所以我们只要考虑 k 小于这个临界值的询问(大于的直接取模就行

再将询问离线下来

将 n 次操作视为每次给每个点 +1,记为 (h[i]) 。然后排一遍序。设一个指针为 p ,从最低的向高位依次推进,当每遇到一个新的 h 时,我们考虑前p个数都需要再举办到 h 次,然后才能向下枚举。这时我们的问题就只关于这前 p 个数,前 p 个数又一共需要举办 (h imes p) 次,所以只要一个询问不大于 (h imes p) ,我们就在本次解决,然后需要查询一下前 p 个数的下标第 k 大,这里使用树状数组上倍增解决。

凭借树状数组的小常数,目前成功苟在 rk2

#include<bits/stdc++.h>

using namespace std;

#define int long long
#define lowbit(x) (x & (-x))

char xch,xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
template<typename _T>
inline int read(_T &x)
{
    x=0;
	int f=1;char ch=getc();
    while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}

const int np = 5e5 + 5;
struct query{
	int tim;
	int id;
	friend bool operator<(const query &a,const query &b)
	{
		return a.tim < b.tim;
	}
	
}qry[np + 10];
int n,h[np + 10],b[np + 10],index[np + 10];
int lg[np + 10];
int tree[np + 10],ans[np + 10];

inline bool cmp(int a,int b)
{
	return h[a] < h[b];
}

inline int add(int x)
{
	while(x <= n)
	{
		tree[x] += 1;
		x += lowbit(x);
	}
}

inline int binary(int kth)
{
	int res = 0;
	int step = 0;
	kth--;
	for(int i=lg[n];i>=0;i--)
	{
		if(step + (1 << i) > n) continue;
		if(res + tree[step + (1 << i)] <= kth)
		{
			res += tree[step + (1 << i)];
			step += 1 << i;
		}
	}
	return step + 1;
}

signed  main()
{
	int m,q;
	read(m);
	read(n);
	read(q);
	for(int i=1,x;i<=m;i++)
	{
		read(x);
		h[x] ++ ;
	 }
	int maxn = 0;
	for(int i=1;i<=n;i++) maxn = max(maxn , b[i]= h[i]),index[i] = i; 
	for(int i=2;i<=n;i++) lg[i] = lg[i>>1] + 1;
	
	int lim = maxn * n - m;
	
	sort(b + 1,b + 1 + n);
	sort(index + 1,index + 1 + n,cmp);
	
	for(int i=1,x;i<=q;i++)
	{
		read(x);
		x -= m;
		qry[i] = (query){x,i};
	}
	sort(qry + 1,qry + 1 + q);
	
	int p = 1;
	int res = 0;
	add(index[1]);
	for(int i=1;i<=q;)
	{
		if(qry[i].tim> lim)
		{
			if((qry[i].tim-lim) % n == 0) ans[qry[i].id] = n;
			else ans[qry[i].id] = (qry[i].tim-lim) % n;
			i++;
			continue;
		}
		while(b[p + 1] == b[p]) add(index[++p]);
		int c = b[p + 1] - b[p];
		while(res < qry[i].tim && qry[i].tim <= res + p * c)
		{
			int g = qry[i].tim - res;
			if(g % p == 0) g = binary(p);
			else g = binary(g%p);
			ans[qry[i].id] = g;
			i++;
		}
		res += p * c;
		p++;
		add(index[p]);
	}
	
	for(int i=1;i<=q;i++)
		printf("%lld ",ans[i]);
	return 0;
 }
原文地址:https://www.cnblogs.com/-Iris-/p/15342316.html