zoukankan      html  css  js  c++  java
  • 「CF643G」 Choosing Ads

    「CF643G」 Choosing Ads

    传送门

    如果你知道摩尔投票法可以扩展事实上是个一眼题,又好写又好调。

    首先摩尔投票法是用来求众数定义为超过所有数个数一半的数的一个算法。

    大致算法流程:

    • 将第一个数其设为我们预选的众数,并给其一个权值 (w=1)
    • 接下来,每当我们遍历一个数,若其与预选的众数相同,便使其权值加一,否则使其减一。
    • 若预选的众数权值变为 (0),则将使其变为 (0) 的这个数设为预选的众数。

    最后留下的数就是答案。

    然后这东西显然可以通过线段树进行合并。

    然后这个东西你发现,如果我们不止预选一个数,而是预选 (k) 个数,我们就可以求出出现概率超过 (frac {1}{k+1}) 的众数。

    然后这个题就没了。

    /*---Author:HenryHuang---*/
    /*---Never Settle---*/
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1.5e5+5;
    vector<pair<int,int> > tree[maxn<<2];
    int tag[maxn<<2];
    int n,m,p;
    int a[maxn];
    vector<pair<int,int> > merge(vector<pair<int,int> > a,vector<pair<int,int> > b){
    	for(auto [x,y]:b){
    		int flag=0;
    		for(auto &[xx,yy]:a){
    			if(xx==x){
    				yy+=y,flag=1;
    				break;
    			}
    		}
    		if(flag) continue;
    		a.emplace_back(x,y);
    		if((int)a.size()<=p) continue;
    		int mn=n;
    		for(auto [xx,yy]:a) mn=min(mn,yy);
    		vector<pair<int,int> > tmp;
    		for(auto [xx,yy]:a)
    			if(yy-mn) tmp.emplace_back(xx,yy-mn);
    		a=tmp;
    	}
    	return a;
    }
    void reset(int t,int len,int num){
    	tree[t].clear();
    	tree[t].emplace_back(num,len);
    }
    void down(int t,int ls,int rs){
    	if(tag[t]){
    		tag[t<<1]=tag[t],tag[t<<1|1]=tag[t];
    		reset(t<<1,ls,tag[t]),reset(t<<1|1,rs,tag[t]);
    		tag[t]=0;
    	}
    }
    void build(int l,int r,int t){
    	if(l==r){
    		tree[t].emplace_back(a[l],1);
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,t<<1);
    	build(mid+1,r,t<<1|1);
    	tree[t]=merge(tree[t<<1],tree[t<<1|1]);
    }
    void modify(int ll,int rr,int l,int r,int num,int t){
    	if(ll<=l&&r<=rr){
    		reset(t,r-l+1,num),tag[t]=num;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	down(t,mid-l+1,r-mid);
    	if(ll<=mid) modify(ll,rr,l,mid,num,t<<1);
    	if(rr>mid) modify(ll,rr,mid+1,r,num,t<<1|1);
    	tree[t]=merge(tree[t<<1],tree[t<<1|1]);
    }
    vector<pair<int,int> > query(int ll,int rr,int l,int r,int t){
    	if(ll<=l&&r<=rr) return tree[t];
    	int mid=(l+r)>>1;
    	down(t,mid-l+1,r-mid);
    	vector<pair<int,int> > tmp;
    	if(ll<=mid) tmp=merge(tmp,query(ll,rr,l,mid,t<<1));
    	if(rr>mid) tmp=merge(tmp,query(ll,rr,mid+1,r,t<<1|1));
    	return tmp;
    }
    int main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	cin>>n>>m>>p;p=100/p;
    	for(int i=1;i<=n;++i) cin>>a[i];
    	build(1,n,1);
    	for(int i=1;i<=m;++i){
    		int opt,l,r,v;cin>>opt>>l>>r;
    		if(opt==1){
    			cin>>v;
    			modify(l,r,1,n,v,1);
    		}
    		else{
    			auto ans=query(l,r,1,n,1);
    			cout<<ans.size()<<' ';
    			for(auto [x,y]:ans) cout<<x<<' ';
    			cout<<'
    ';
    		}
    	}
    	return 0;
    }
    
    在繁华中沉淀自我,在乱世中静静伫立,一笔一划,雕刻时光。
  • 相关阅读:
    弹出窗口的几种方法
    FCKeditor2.2+ASP.NET2.0不完全攻略
    如何运用 Form 表单认证 ?
    DataGrid的多种格式化显示方法
    如何显示在线人数,和所在位置?? [转自作者:子扬]
    备份和恢复Active Directory
    如何在vs.net里调试脚本 《一》
    初学ASP.Net时一些备忘的东西
    ASP.NET在线用户列表精确版——解决用户意外退出在线列表无法及时更新问题
    小技巧(一)分离字符串string str="(1,10,100,1000,10000,)";
  • 原文地址:https://www.cnblogs.com/HenryHuang-Never-Settle/p/solution-CF643G.html
Copyright © 2011-2022 走看看