CF467G

T2 CF467G

  • 给定一个长度为 n 的序列和一个整数p。
  • 有 m个操作,操作要么是区间赋值,要么是询问区间内出现次数至少占 p% 的数。
  • 输出询问的答案时,可以包含错的数,也可以重复输出,但对的数一定要在答案中,且输出的数的个数不超过 \(\lfloor \frac{100}{p}\rfloor\)
  • \(n,m \le 1.5 \times 10^5,20 \le p \le 100\)

若p >= 51时 等价于求区间绝对众数

在考虑若 \(20 \le p \le 50\) 则维护至多5个出现次数最多的数即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int N = 1.5e5+10;
inline int read()
{
	register int x = 0 , f = 0; register char c = getchar();
	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
	return f ? -x : x;
}
int n , m , p;
struct node
{
	int siz , tag , a[6] , b[6]; // siz 数量 , a 出现次数最多的数 , b 出现次数 
	node() { memset(a , 0 , sizeof a); memset(b , 0 , sizeof b); siz = tag = 0; }
	inline node operator = (const node &o)
	{
		siz = o.siz; tag = 0; // tag 清0 , 好像是防止叶子的tag被瞎用。。。。 
		memcpy(a , o.a , sizeof a);
		memcpy(b , o.b , sizeof b);
		return *this;
	}
	node operator + (const node &A) const 
	{
		node res = A;
		for(int i = 1 ; i <= siz ; ++i)
		{
			int flag = 0;
			for(int j = 1 ; j <= res.siz ; ++j)
				if(a[i] == res.a[j]) { res.b[j] += b[i]; flag = 1; break; }
			if(flag) continue;
			if(res.siz < p) { res.siz++; res.a[res.siz] = a[i]; res.b[res.siz] = b[i]; continue; }
			
			int k = 1;
			for(int j = 2 ; j <= res.siz ; ++j) if(res.b[k] > res.b[j]) k = j;
			if(b[i] < res.b[k])
				for(int j = 1 ; j <= res.siz ; ++j) res.b[j] -= b[i];
			else
			{
				int tmp = res.b[k];
				res.a[k] = a[i]; res.b[k] = b[i];
				for(int j = 1 ; j <= res.siz ; ++j) res.b[j] -= tmp;
			}
		}
		return res;
	}
}tr[N << 2];

#define lson k << 1 , l , mid
#define rson k << 1 | 1 , mid + 1 , r

inline void update(int k) { tr[k] = tr[k << 1] + tr[k << 1 | 1]; return ; }

void build(int k , int l , int r)
{
	if(l == r) { tr[k].a[1] = read(); tr[k].b[1] = tr[k].siz = 1; return ; }
	int mid = (l + r) >> 1;
	build(lson); build(rson); return update(k);
}

inline void Tag(int k , int l , int r , int val)
{
	tr[k].a[1] = val; tr[k].b[1] = r - l + 1; tr[k].siz = 1; tr[k].tag = val; return ;
}

inline void down(int k , int l , int r)
{
	if(tr[k].tag)
	{
		int mid = (l + r) >> 1;
		Tag(lson , tr[k].tag); Tag(rson , tr[k].tag);
		tr[k].tag = 0;
	}
	return ; 
}

void modify(int k , int l , int r , int x , int y , int val)
{
	if(x <= l && r <= y) return Tag(k , l , r , val);
	int mid = (l + r) >> 1; down(k , l , r);
	if(x <= mid) modify(lson , x , y , val);
	if(y  > mid) modify(rson , x , y , val);
	return update(k);
}

node Ask(int k , int l , int r , int x , int y)
{
	if(x <= l && r <= y) return tr[k];
	int mid = (l + r) >> 1; down(k , l , r);
	if(y <= mid) return Ask(lson , x , y);
	if(x  > mid) return Ask(rson , x , y);
	return Ask(lson , x , y) + Ask(rson , x , y);
}

int main()
{
	n = read(); m = read(); p = 100 / read();
	build(1 , 1 , n);
	int op , l , r , x;
	while(m--)
	{
		op = read(); l = read(); r = read();
		if(op == 1) x = read() , modify(1 , 1 , n , l , r , x);
		if(op == 2)
		{
			node s = Ask(1 , 1 , n , l , r); cout << s.siz;
			for(int i = 1 ; i <= s.siz ; ++i) cout << ' ' << s.a[i]; cout << '\n';
		}
	}
	return 0;
}
posted @ 2020-05-31 06:22  沙野博士  阅读(211)  评论(0)    收藏  举报