zoukankan      html  css  js  c++  java
  • 【BZOJ4966】总统选举 线段树+随机化

    【BZOJ4966】总统选举

    Description

    黑恶势力的反攻计划被小C成功摧毁,黑恶势力只好投降。秋之国的人民解放了,举国欢庆。此时,原秋之国总统因没能守护好国土,申请辞职,并请秋之国人民的大救星小C钦定下一任。作为一名民主人士,小C决定举行全民大选来决定下一任。为了使最后成为总统的人得到绝大多数人认同,小C认为,一个人必须获得超过全部人总数的一半的票数才能成为总统。如果不存在符合条件的候选人,小C只好自己来当临时大总统。为了尽可能避免这种情况,小C决定先进行几次小规模预选,根据预选的情况,选民可以重新决定自己选票的去向。由于秋之国人数较多,统计投票结果和选票变更也成为了麻烦的事情,小C找到了你,让你帮他解决这个问题。
     
    【问题描述】
    秋之国共有n个人,分别编号为1,2,…,n,一开始每个人都投了一票,范围1~n,表示支持对应编号的人当总统。共有m次预选,每次选取编号[li,ri]内的选民展开小规模预选,在该区间内获得超过区间大小一半的票的人获胜,如果没有人获胜,则由小C钦定一位候选者获得此次预选的胜利(获胜者可以不在该区间内),每次预选的结果需要公布出来,并且每次会有ki个人决定将票改投向该次预选的获胜者。全部预选结束后,公布最后成为总统的候选人 

    Input

    第一行两个整数n,m,表示秋之国人数和预选次数。
    第二行n个整数,分别表示编号1~n的选民投的票。
    接下来m行,每行先有4个整数,分别表示li,ri,si,ki,si表示若此次预选无人胜选,视作编号为si的人获得胜利
    接下来ki个整数,分别表示决定改投的选民。
    1<=n,m<=500,000,Σki<=1,000,000,1<=li<=ri<=n,1<=si<=n。

    Output

    共m+1行,前m行表示各次预选的结果,最后一行表示最后成为总统的候选人,若最后仍无人胜选,输出-1。

    Sample Input

    5 4
    1 2 3 4 5
    1 2 1 1 3
    5 5 1 2 2 4
    2 4 2 0
    3 4 2 1 4

    Sample Output

    1
    5
    5
    2
    -1

    题解:正解见Claris的博客

    然而本人还是用随机化过的,并且由于姿势太弱,在时间上略有点卡。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    int n,m,tot;
    const int maxn=500010;
    const int tim=15;
    int rt[maxn],v[maxn];
    struct node
    {
    	int siz,ls,rs;
    }s[maxn*60];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void insert(int &x,int l,int r,int y,int v)
    {
    	if(!x)	x=++tot;
    	s[x].siz+=v;
    	if(l==r)	return ;
    	int mid=l+r>>1;
    	if(y<=mid)	insert(s[x].ls,l,mid,y,v);
    	else	insert(s[x].rs,mid+1,r,y,v);
    }
    int query(int x,int l,int r,int a,int b)
    {
    	if(!x)	return 0;
    	if(a<=l&&r<=b)	return s[x].siz;
    	int mid=l+r>>1;
    	if(b<=mid)	return query(s[x].ls,l,mid,a,b);
    	if(a>mid)	return query(s[x].rs,mid+1,r,a,b);
    	return query(s[x].ls,l,mid,a,b)+query(s[x].rs,mid+1,r,a,b);
    }
    int main()
    {
    	srand(2333666);
    	n=rd(),m=rd();
    	int i,j,a,b,c,d;
    	for(i=1;i<=n;i++)	v[i]=rd(),insert(rt[v[i]],1,n,i,1);
    	for(i=1;i<=m;i++)
    	{
    		a=rd(),b=rd();
    		for(j=1;j<=tim;j++)
    		{
    			c=v[rand()%(b-a+1)+a];
    			if(query(rt[c],1,n,a,b)>(b-a+1)/2)	break;
    		}
    		if(j<=tim)	rd();
    		else	c=rd();
    		printf("%d
    ",c);
    		d=rd();
    		for(j=1;j<=d;j++)	a=rd(),insert(rt[v[a]],1,n,a,-1),v[a]=c,insert(rt[c],1,n,a,1);
    	}
    	for(i=1;i<=n;i++)	if(s[rt[i]].siz>n/2)
    	{
    		printf("%d
    ",i);
    		return 0;
    	}
    	printf("-1");
    	return 0;
    }//5 4 1 2 3 4 5 1 2 1 1 3 5 5 1 2 2 4 2 4 2 0 3 4 2 1 4
  • 相关阅读:
    HTTP浅析
    PHP CURL获取cookies模拟登录
    C++ builder 通过WMI方式修改DNS
    C语言List使用样例
    C语言 获取系统临时目录并获取临时文件名
    C语言 写文件样例
    vb wmi 修改ip地址、网关、DNS
    正则表达式校验IP地址
    c语言 vector使用样例
    C++ builder 通过WMI查询网卡对应的序号
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7412218.html
Copyright © 2011-2022 走看看