题解 [CF643G] Choosing Ads

传送门

还是先来口胡一个做法:
发现只有每次区间内出现次数 \(\geqslant p\%\) 的数是有用的,考虑怎么合并两个区间
发现新区间内出现次数 \(\geqslant p\%\) 的数一定在原区间出现次数 \(\geqslant p\%\) 的数中间
那么对每个可能的数 \(O(\log n)\) 查询一下在新区间中的出现次数即可
复杂度 \(O(nk\log^2n)\)

然后正解:

  • 关于摩尔投票法由绝对众数向出现次数 \(\geqslant p\%\) 的推广:
    考虑摩尔投票法是每次从序列里选两个不一样的删掉
    \(k=\lfloor\frac{100}{p}\rfloor\),那么考虑每次选 \(k+1\) 个两两不同的删掉即可

于是线段树上大力维护这个东西
复杂度 \(O(nk^2\log n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define fir first
#define sec second
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, p;
int a[N], k;
struct vec{
	int siz;
	pair<int, int> a[11];
	vec():siz(0){memset(a, 0, sizeof(a));}
	inline pair<int, int>& operator [] (int t) {return a[t];}
	inline void set(int val, int cnt) {a[siz=1]={val, cnt};}
}dat[N<<2], ans;
inline vec operator + (vec a, vec b) {
	vec ans=a;
	for (int i=1; i<=b.siz; ++i) {
		for (int j=1; j<=ans.siz; ++j) if (ans[j].fir==b[i].fir) {ans[j].sec+=b[i].sec; goto jump;}
		ans[++ans.siz]=b[i];
		jump: ;
	}
	sort(ans.a+1, ans.a+ans.siz+1, [](pair<int, int> a, pair<int, int> b){return a.sec>b.sec;});
	for (; ans.siz>k; --ans.siz) for (int i=ans.siz-k; i<ans.siz; ++i) ans[i].sec-=ans[ans.siz].sec;
	return ans;
}
#define tl(p) tl[p]
#define tr(p) tr[p]
#define pushup(p) dat[p]=dat[p<<1]+dat[p<<1|1]
int tl[N<<2], tr[N<<2], len[N<<2], tag[N<<2];
void spread(int p) {
	if (!tag[p]) return ;
	dat[p<<1].set(tag[p], len[p<<1]); tag[p<<1]=tag[p];
	dat[p<<1|1].set(tag[p], len[p<<1|1]); tag[p<<1|1]=tag[p];
	tag[p]=0;
}
void build(int p, int l, int r) {
	tl(p)=l; tr(p)=r; len[p]=r-l+1;
	if (l==r) {dat[p].set(a[l], 1); return ;}
	int mid=(l+r)>>1;
	build(p<<1, l, mid);
	build(p<<1|1, mid+1, r);
	pushup(p);
}
void upd(int p, int l, int r, int val) {
	if (l<=tl(p)&&r>=tr(p)) {dat[p].set(val, len[p]); tag[p]=val; return ;}
	spread(p);
	int mid=(tl(p)+tr(p))>>1;
	if (l<=mid) upd(p<<1, l, r, val);
	if (r>mid) upd(p<<1|1, l, r, val);
	pushup(p);
}
vec query(int p, int l, int r) {
	if (l<=tl(p)&&r>=tr(p)) return dat[p];
	spread(p);
	int mid=(tl(p)+tr(p))>>1;
	if (l<=mid&&r>mid) return query(p<<1, l, r)+query(p<<1|1, l, r);
	else if (l<=mid) return query(p<<1, l, r);
	else return query(p<<1|1, l, r);
}

signed main()
{
	n=read(); m=read(); p=read(); k=100/p;
	for (int i=1; i<=n; ++i) a[i]=read();
	build(1, 1, n);
	for (int i=1,l,r,val; i<=m; ++i) {
		if (read()&1) {
			l=read(); r=read(); val=read();
			upd(1, l, r, val);
		}
		else {
			l=read(); r=read();
			ans=query(1, l, r);
			printf("%d ", ans.siz);
			for (int j=1; j<=ans.siz; ++j) printf("%d ", ans[j].fir);
			printf("\n");
		}
	}

	return 0;
}
posted @ 2022-05-26 20:12  Administrator-09  阅读(2)  评论(0编辑  收藏  举报