• bzoj3524[Poi2014]Couriers


    Description

    给一个长度为n的序列a。1≤a[i]≤n。
    m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

    Input

    第一行两个数n,m。
    第二行n个数,a[i]。
    接下来m行,每行两个数l,r,表示询问[l,r]这个区间。

    Output

    m行,每行对应一个答案。

    Sample Input

    7 5
    1 1 3 2 3 4 3
    1 3
    1 4
    3 7
    1 7
    6 6

    Sample Output

    1
    0
    3
    0
    4

    HINT

    【数据范围】

    n,m≤500000

    第一次打可持久化线段树……

    可持久化线段树是这样一个数据结构:它不仅实现线段树的操作,而且可以访问线段树的历史版本。

    做法是“建n棵线段树”。

    当然不是n^2logn的满二叉树啦

    对于这题:首先搞出一颗权值线段树(就是区间(l,r)表示数字大小在(l,r)中的有多少个,a[i]<=10^9之类太大的要离散搞)。

    每次增加一个数k进去的时候,相当于从根节点到叶节点的所有包含k的区间的sum+1。

    但是我们要保留以前的版本,怎么做呢?

    很容易发现每次加入一个k,修改的都只有树上的一条从根到叶的链上的sum,也就是说其他数据我们是可以共用的

    所以每次加入k的时候只要再插入一条链就可以完成修改。

    比如当前我们插入链做到一个点,首先把它的左右儿子改成它的上一个版本的左右儿子。然后看k在左边还是右边,再往那一边继续递归下去

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define mx 10000010
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,treesize;
    int root[500001];
    int ls[mx],rs[mx],tot[mx];
    inline void insert(int l,int r,int x,int &y,int dat)
    {
    	y=++treesize;
    	tot[y]=tot[x]+1;
    	if (l==r) return;
    	ls[y]=ls[x];rs[y]=rs[x];
    	int mid=(l+r)>>1;
    	if (dat<=mid)insert(l,mid,ls[x],ls[y],dat);
    	else insert(mid+1,r,rs[x],rs[y],dat);
    }
    inline int ask(int l,int r)
    {
    	int ll=1,rr=n,request=(r-l+1)>>1;
    	int x=root[l-1],y=root[r];
    	while (ll!=rr)
    	{
    		if (tot[y]-tot[x]<=request) return 0;
    		int mid=(ll+rr)>>1;
    		if (tot[ls[y]]-tot[ls[x]]>request)
    		{rr=mid;x=ls[x];y=ls[y];}
    		else if (tot[rs[y]]-tot[rs[x]]>request)
    		{ll=mid+1;x=rs[x];y=rs[y];}
    		else return 0;
    	}
    	return ll;
    }
    int main()
    {
    	n=read();m=read();
    	for (int i=1;i<=n;i++)
    	{
    		int x=read();
    		insert(1,n,root[i-1],root[i],x);
    	}
    	for (int i=1;i<=m;i++)
    	{
    		int x=read(),y=read();
    		printf("%d
    ",ask(x,y));
    	}
    }


    ——by zhber,转载请注明来源
  • 相关阅读:
    Chrome 中的彩蛋,一款小游戏,你知道吗?
    Json对象与Json字符串互转(4种转换方式)
    [PHP自动化-进阶]005.Snoopy采集框架介绍
    [PHP自动化-进阶]004.Snoopy VS CURL 模拟Discuz.net登陆
    [PHP自动化-进阶]003.CURL处理Https请求访问
    [PHP自动化-进阶]002.CURL模拟登录带有验证码的网站
    [PHP自动化-进阶]001.CURL模拟登录并采集数据
    [注]2015中国程序员生存报告,你苦你先看@^@
    [JavaWeb基础] 016.Struts2 国际化配置
    [工具推荐]_iOS音频批量转换
  • 原文地址:https://www.cnblogs.com/zhber/p/4035959.html
Copyright © 2020-2023  润新知