zoukankan      html  css  js  c++  java
  • 题解 P3567 [POI2014]KUR-Couriers

    题意翻译

    给一个长度为 (n) 的正整数序列 (a)。共有 (m) 组询问,每次询问一个区间 ([l,r]) ,是否存在一个数在$ [l,r]$ 中出现的次数严格大于一半。如果存在,输出这个数,否则输出 (0)

    (1 leq n,m leq 5 imes 10^5,0 leq a_i leq n.)

    分析

    是主席树的板子题,不过用莫队也可以做。

    这里讲一下主席树的做法。(其实也没有什么做法)。。

    利用前缀和的性质,我们可以得到 ([L,R]) 中的元素组成的权值线段树。

    从根节点开始,

    我们假设存在 该严格众数。

    那么

    • 该数的出现次数 (>(r-l+1)/2) ----------> 该数所在区间的 (sum > (r-l+1)/2)
    • 又某节点的左右子树中至多只有一个满足该性质,(总共才 ((r-l+1)) 个元素)。
    • 所以,如果有子树满足该性质,那么往这个子树走,
    • 如果一个都没有,那么不存在严格众数,返回0.

    Code:

    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    #define rint register int
    using namespace std;
    namespace FastIO
    {
    char c;
    bool sign;
    template<class T>
    inline void read(T &x)
    {
    	x=0;
    	sign=false;
    	for(c=getchar();c<'0'||c>'9';c=getchar()) 
    		if(c=='-') 
    			sign=true;
    	for(;c>='0'&&c<='9';c=getchar())
    		x=(x<<1)+(x<<3)+(c&15);
    	if(sign) x=~x+1;
     	return;
    }
    template<class T>
    void print(T x)
    {
    	if(x<0) putchar('-'),x=~x+1;
    	if(x>9) print(x/10);
    	putchar(x%10+'0');
    	return;
    }
    }
    using FastIO::read;
    using FastIO::print;
    //================================================
    const int N=5e5+5;
    struct Node
    {
    	int lc,rc;
    	int sum;
    }hjt[32*N];
    int cnt=0;
    int root[N];
    void insert(int &now,const int &pre,const int &key,const int &l,const int &r)
    {
    	hjt[now=++cnt]=hjt[pre];
    	hjt[now].sum++;
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	if(key<=mid) insert(hjt[now].lc,hjt[pre].lc,key,l,mid);
    	else insert(hjt[now].rc,hjt[pre].rc,key,mid+1,r);
    	return;
    }
    int query(const int &L,const int &R,const int &l,const int &r,const int &lit) //(L,R]
    {
    	if(l==r) return l;
    	int mid=(l+r)>>1;
    	if(hjt[hjt[R].lc].sum-hjt[hjt[L].lc].sum>lit) 
    		return query(hjt[L].lc,hjt[R].lc,l,mid,lit);
    	else if(hjt[hjt[R].rc].sum-hjt[hjt[L].rc].sum>lit)
    		return query(hjt[L].rc,hjt[R].rc,mid+1,r,lit);
    	else return 0;
    }
    int a[N];
    int n,m;
    vector<int> v;
    int main()
    {
    //	freopen("1.in","r",stdin);
    	rint i;
    	int x,y,z;
    	read(n); read(m);
    	for(i=1;i<=n;i++) {
    		read(a[i]);
    		v.push_back(a[i]);
    	}
    	sort(v.begin(),v.end());
    	v.erase(unique(v.begin(),v.end()),v.end());
    	for(i=1;i<=n;i++) 
    		a[i]=(int)(lower_bound(v.begin(),v.end(),a[i])-v.begin())+1;
    	for(i=1;i<=n;i++) 
    		insert(root[i],root[i-1],a[i],1,v.size());
    	while(m--) {
    		read(x); read(y);
    		z=query(root[x-1],root[y],1,v.size(),(y-x+1)>>1);
    		if(z==0) puts("0");
    		else print(v[z-1]),putchar('
    ');
    	}
    	return 0;
    }
    

    虽然题目的数据范围不需要离散化,但我还是离散化了一下,(但愿会快一点)。

    另外第一次用 (scanf)(printf) 交上去T了,

    (5 imes 10^{5}) 的数据范围下,用快读快输大概会比 (scanf space printf) 稳定的快上 (100ms - 150ms)


    P.S:还有两种很巧妙的做法。

  • 相关阅读:
    RxJava学习经验谈——map与flatmap
    不要打断链式结构:使用 RxJava的 compose() 操作符
    Android Retrofit网络请求Service,@Path、@Query、@QueryMap、@Map...
    Android 勤用RXJava compose操作符消除重复代码
    Android使用token维持登陆状态的方法
    Java服务器对外提供接口以及Android端向服务器请求数据
    Retrofit请求数据对错误以及网络异常的处理
    Retrofit2.0+OkHttp打印Request URL(请求地址参数)
    HUE配置文件hue.ini 的hbase模块详解(图文详解)(分HA集群和非HA集群)
    安装Hue后的一些功能的问题解决干货总结(博主推荐)
  • 原文地址:https://www.cnblogs.com/cjl-world/p/13172199.html
Copyright © 2011-2022 走看看