【Codeforces 643G】—Choosing Ads(线段树)

传送门

考虑O(n)O(n)求区间绝对众数的方法
维护当前值vv和次数kk
如果当前这个值̸=v,k\not =v,k--
否则k++k++
如果k<0,v=a[i]k<0,v=a[i]
这样保证最后得到的一定是出现次数>n/2>n/2

出现次数>n/p>n/p的类似
线段树维护每个区间的
合并2个区间只需要把2边的前100/p100/p个拿来合并
仍然是对的

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=150005;
cs int C=11;
struct Val{
	int val,siz;
	friend inline bool operator <(cs Val &a,cs Val &b){
		return a.siz>b.siz;
	}
};
int n,q,a[N],S,P;
struct node{
	int len;Val v[C]; 
	node(){len=0;}
	inline void init(int val,int siz){
		len=1,v[1].val=val,v[1].siz=siz;
	}
	friend inline node operator +(cs node &a,cs node &b){
		node c=a;
		for(int i=1;i<=b.len;i++){
			bool fg=0;
			for(int j=1;j<=c.len;j++)
			if(b.v[i].val==c.v[j].val){
				c.v[j].siz+=b.v[i].siz,fg=1;
			}
			if(!fg)c.v[++c.len]=b.v[i];
		}
		if(c.len>S){
			sort(c.v+1,c.v+c.len+1);
			for(int i=c.len;i>S;i--)
			for(int j=1;j<=i;j++)
			c.v[j].siz-=c.v[i].siz;
			while(c.len&&c.v[c.len].siz<=0)c.len--;
		}
		return c;
	}
};
namespace Seg{
	node tr[N<<2];
	int tag[N<<2];
	#define lc (u<<1)
	#define rc ((u<<1)|1)
	#define mid ((l+r)>>1)
	inline void pushup(int u){
		tr[u]=tr[lc]+tr[rc];
	}
	inline void pushnow(int u,int l,int r,int k){
		tag[u]=k,tr[u].init(k,r-l+1);
	}
	inline void pushdown(int u,int l,int r){
		if(!tag[u])return;
		pushnow(lc,l,mid,tag[u]);
		pushnow(rc,mid+1,r,tag[u]);
		tag[u]=0;
	}
	void build(int u,int l,int r){
		if(l==r){
			tr[u].init(a[l],1);return ;
		}
		build(lc,l,mid),build(rc,mid+1,r);
		pushup(u);
	}
	void update(int u,int l,int r,int st,int des,int k){
		if(st<=l&&r<=des)return pushnow(u,l,r,k);
		pushdown(u,l,r);
		if(st<=mid)update(lc,l,mid,st,des,k);
		if(mid<des)update(rc,mid+1,r,st,des,k);
		pushup(u);
	}
	node query(int u,int l,int r,int st,int des){
		if(st<=l&&r<=des)return tr[u];
		pushdown(u,l,r);
		node res;
		if(des<=mid)res=query(lc,l,mid,st,des);
		else if(mid<st)res=query(rc,mid+1,r,st,des);
		else res=query(lc,l,mid,st,des)+query(rc,mid+1,r,st,des);
		pushup(u);return res;
	}
}
int main(){
	n=read(),q=read(),P=read(),S=100/P;
	for(int i=1;i<=n;i++)a[i]=read();
	Seg::build(1,1,n);
	while(q--){
		int op=read(),l=read(),r=read();
		if(op==1){
			int id=read();
			Seg::update(1,1,n,l,r,id);
		}
		else{
			node res=Seg::query(1,1,n,l,r);
			cout<<res.len<<" ";
			for(int i=1;i<=res.len;i++)cout<<res.v[i].val<<" ";puts("");
		}
	}
}
posted @ 2019-09-10 21:41  Stargazer_cykoi  阅读(120)  评论(0编辑  收藏  举报