zoukankan      html  css  js  c++  java
  • POJ-2886 Who Gets the Most Candies?(线段树+模拟)

    题目大意:n个小孩按顺时针站成一圈,每次会有一个小孩出队(第一个出队的小孩已知),在他出队时会指定下一个出队的小孩,直到所有的小孩全部出队游戏结束。第p个出队的小孩会得到f(p)个糖果,f(p)为p的正约数个数。问获得最多糖果的小孩是谁?并求出他获得的糖果数。如果有多解,只输出最先出队的那个小孩。

    题目分析:先将1~n之内的具有最多约数个数并且最小的那个数打出来,然后模拟相应的次数操作即可。模拟时利用到线段树,用线段树维护区间中有多少个小孩还没有出队,每次出队一个小孩就将他在树中删除,最后利用线段树查询下一个应该出队的小孩

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int N=500000;
    
    int f[N+5];
    int tab[N+5];
    int tr[N*4+5];
    char p[N+5][12];
    int next[N+5];
    
    void init()
    {
    	memset(tab,0,sizeof(tab));
    	for(LL i=1;i<=N;++i){
    		if(i*i<=N) ++tab[i*i];
    		for(LL j=i+1;i*j<=(LL)N;++j)
    			tab[i*j]+=2;
    	}
    	f[1]=1;
    	for(int i=2;i<=N;++i){
    		if(tab[i]>tab[f[i-1]])
    			f[i]=i;
    		else
    			f[i]=f[i-1];
    	}
    }
    
    void makeTree(int rt,int l,int r)
    {
    	if(l==r)
    		tr[rt]=1;
    	else{
    		int mid=l+(r-l)/2;
    		makeTree(rt<<1,l,mid);
    		makeTree(rt<<1|1,mid+1,r);
    		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
    	}
    }
    
    void update(int rt,int l,int r,int x)
    {
    	if(l==r)
    		--tr[rt];
    	else{
    		int mid=l+(r-l)/2;
    		if(x<=mid) update(rt<<1,l,mid,x);
    		else update(rt<<1|1,mid+1,r,x);
    		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
    	}
    }
    
    int query1(int rt,int l,int r,int L,int R)
    {
    	if(L>R) return 0;
    	if(L<=l&&r<=R)
    		return tr[rt];
    	else{
    		int res=0;
    		int mid=l+(r-l)/2;
    		if(L<=mid) res+=query1(rt<<1,l,mid,L,R);
    		if(R>mid) res+=query1(rt<<1|1,mid+1,r,L,R);
    		return res;
    	}
    }
    
    int query2(int rt,int l,int r,int cnt)
    {
    	if(l==r) return l;
    	int mid=l+(r-l)/2;
    	if(tr[rt<<1]>=cnt)
    		return query2(rt<<1,l,mid,cnt);
    	else
    		return query2(rt<<1|1,mid+1,r,cnt-tr[rt<<1]);
    }
    
    int main()
    {
    	init();
    	int n,k;
    	while(~scanf("%d%d",&n,&k))
    	{
    		for(int i=0;i<n;++i)
    			scanf("%s%d",p[i],&next[i]);
    		memset(tr,0,sizeof(tr));
    		makeTree(1,0,n-1);
    		int now=k-1;
    		for(int i=1;i<f[n];++i){
    			int l=query1(1,0,n-1,0,now-1);
    			int r=query1(1,0,n-1,now+1,n-1);
    			int nn;
    			if(next[now]>0)
    				nn=(l-1+next[now]+l+r)%(l+r);
    			else{
    				next[now]=-next[now];
    				next[now]%=(l+r);
    				nn=(l-next[now]+l+r)%(l+r);
    			}
    			update(1,0,n-1,now);
    			now=query2(1,0,n-1,nn+1);
    		}
    		printf("%s %d
    ",p[now],tab[f[n]]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    (转载)Android mac 真机调试
    Google Map SDK for iOS
    autolayout under navigation bar
    Xamarin Mono For Android、Monotouch 安装
    不错的ORM调试查看SQL插件
    在Windows 8.1系统上配置免安装版mysql-5.6.21-winx64
    VS2013 EF6连接MySql
    安卓离线SDK Windows版 资源包下载地址全集
    WndProc函数参数列表
    反射创建对象
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5462337.html
Copyright © 2011-2022 走看看