zoukankan      html  css  js  c++  java
  • [bzoj3524/2223][Poi2014]Couriers_主席树

    Couriers bzoj-3524 Poi-2014

    题目大意:给定n个数的序列,询问区间内是否存在一个在区间内至少出现了(区间长度>>1)次的数。如果有,输出该数,反之输出0。

    注释:$1le n,mle 5cdot 10^5$。


    想法:主席树裸题。

    主流做法就是弄一个Existence数组询问有没有这样的数,然后查询区间中位数即可。

    但是可以在query的时候强行查询,因为没有输出0,直接输出即可。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define N 500010
    using namespace std;
    int cnt[N<<5],ls[N<<5],rs[N<<5],tot;
    int a[N],b[N],root[N];
    int build(int l,int r)
    {
    	int pos=++tot,mid=(l+r)>>1;
    	if(l==r) return pos;
    	ls[pos]=build(l,mid); rs[pos]=build(mid+1,r);
    	return pos;
    }
    int update(int pre,int l,int r,int k)
    {
    	int pos=++tot,mid=(l+r)>>1;
    	cnt[pos]=cnt[pre]+1;
    	ls[pos]=ls[pre]; rs[pos]=rs[pre];
    	if(l==r) return pos;
    	if(k<=mid) ls[pos]=update(ls[pre],l,mid,k);
    	else rs[pos]=update(rs[pre],mid+1,r,k);
    	return pos;
    }
    // bool Existence(int x,int y,int l,int r,int Want)
    // {
    // 	if(l==r) return (cnt[y]-cnt[x])>=Want;
    // 	int mid=(l+r)>>1;
    // 	int LR=1;
    // 	if(cnt[ls[y]]-cnt[ls[x]]>cnt[rs[y]]-cnt[rs[x]]) LR=0;
    // 	else if(cnt[ls[y]]-cnt[ls[x]]<cnt[rs[y]]-cnt[rs[x]]) LR=2;
    // 	if(LR==0) return Existence(ls[x],ls[y],l,mid,Want);
    // 	if(LR==2) return Existence(rs[x],rs[y],mid+1,r,Want);
    // 	return Existence(ls[x],ls[y],l,mid,Want)|Existence(rs[x],rs[y],mid+1,r,Want);
    // }
    // int query(int x,int y,int l,int r,int k)
    // {
    // 	int mid=(l+r)>>1;
    // 	if(l==r) return b[l];
    // 	int dlt=cnt[ls[y]]-cnt[ls[x]];
    // 	if(dlt>=k) return query(ls[x],ls[y],l,mid,k);
    // 	else return query(rs[x],rs[y],mid+1,r,k-dlt);
    // }
    int query(int x,int y,int l,int r,int k)
    {
    	int mid=(l+r)>>1;
    	if(l==r) return l;
    	int L=cnt[ls[y]]-cnt[ls[x]],R=cnt[rs[y]]-cnt[rs[x]];
    	if(L>k) return query(ls[x],ls[y],l,mid,k);
    	if(R>k) return query(rs[x],rs[y],mid+1,r,k);
    	else return 0;
    }
    int main()
    {
    	int n,m; cin >> n >> m ;
    	for(int i=1;i<=n;i++) scanf("%d",&a[i])/* ,b[i]=a[i] */;
    	sort(b+1,b+n+1); /* int len=unique(b+1,b+n+1)-b-1; */
    	root[0]=build(1,n);
    	for(int i=1;i<=n;i++)
    	{
    		// int t=lower_bound(b+1,b+n+1,a[i])-b;
    		root[i]=update(root[i-1],1,n,a[i]);
    	}
    	for(int x,y,i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		// if(Existence(root[x-1],root[y],1,n,(y-x+1)/2+1)) printf("%d
    ",query(root[x-1],root[y],1,n,(y-x+1)/2+1));
    		// else printf("0
    ");
    		printf("%d
    ",query(root[x-1],root[y],1,n,(y-x+1)>>1));
    	}
    	return 0;
    }
    

    小结:主席树真强... ...

  • 相关阅读:
    jvm基本结构和解析
    多态的意思
    java中对象的简单解读
    double类型和int类型的区别
    python 解析xml文件
    win10不能映射Ubuntu共享文件
    Qt程序打包
    Ubuntu boot分区文件误删,系统无法启动,怎么解
    ubuntu Boot空间不够问题“The volume boot has only 5.1MB disk space remaining”
    Ubuntu 分辨率更改 xrandr Failed to get size of gamma for output default
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9383690.html
Copyright © 2011-2022 走看看