Time limit 4500 ms

Memory limit 131072 kB

OS Windows

Source 2016中国大学生程序设计竞赛(长春)-重现赛

中文题意

一个长度为n的序列,里面的数字值不超过n(这个题面没说清楚,只说了n和\(a_i\)的上限都是\(2×10^5\))。每次询问一个区间,问这个区间里面,从左到右第一次出现的那些数字组成的新序列,的“中位数”在原序列中出现的位置。比如,假设被询问的区间张这样\(\{1,1,2,2,3,2,5,4\}\),那么里面第一次出现的数字就是\(\{1,2,3,5,4\}\),所求的中位数就是3(按大小排序之后)。另外,这里的“中位数”不同于数学上的,比如\(\{2,3,4,5\}\),答案是3,换句话说,设第一次出现的数字个数为\(len\),那么所求位置是\(\lceil\frac{len}{2}\rceil\),代码里就写成\(\lfloor\frac{len+1}{2}\rfloor\)。

解题思路

首先对于“第一次出现”这一要求,可以参考这里[SDOI2009]HH的项链,从后向前扫的过程中(因为要求第一个出现的,所以要从后往前,确保pos数组最终存着第一个出现的(从前到后也不是搞不出来))使用pos数组记录某数字目前第一次出现的位置,然后用一棵线段树记录区间内“第一次出现的数”的位置,比如,对于序列\(\{1,1,2,2,2,3,3\}\),我们建线段树时所用的序列是\(\{1,0,1,0,0,1,0\}\),在第一次出现某数字的地方加一。这个序列是关键,下面的主席树就是基于这个序列建起来的。

对于“中位数”这一要求,我们可以把上面那个线段树可持久化,套上主席树,从后向前建树,每个位置一个版本,如果当前这个数字在之前建树时出现过,那么就在这个版本的线段树上,把上次出现的位置减1,把这个位置加一,然后更新pos数组。

询问区间\([l,r]\)的时候,先在\(l\)对应的线段树上查询该区间内有多少个第一次出现的数,我的代码里就是quesum()函数,将查询结果——“该区间内第一次出现的数”的数量赋值给k,那么我们要求的答案就是主席树中第\(l\)个版本的线段树上第\(\lfloor\frac{k+1}{2}\rfloor\)个1所在的位置(quek()函数)。(类似区间第k小,但由于这题的题意和从后向前建树的方法,求第k小的时候不用两棵树相减,求一棵树就够了)

文笔不够,感觉有些地方还是不够清楚……我是看yyb的博客看懂的

另外分块也能做这题……HDU 5919 分块做法(留坑不填了)

源代码

#include<stdio.h>
#include<string.h>
#include<algorithm> const int N=200010; int T;
int n,m;
int a[N],pos[N]; struct Node{
int lson,rson;
int sum;
}t[N*40];//这题要40倍才够,32倍都不够。yyb的博客上32倍,那是因为他的N是222222
int root[N],cnt;
/*void build(int &x,int l,int r)
{
x=cnt++;
t[x]={0,0,0};
if(l==r) return;
int mid=l+r>>1;
build(t[x].lson,l,mid);
build(t[x].rson,mid+1,r);
}*/
void update(int &x,int pre,int l,int r,int pos,int delta)
{
x=cnt++;
t[x] = t[pre];
t[x].sum+=delta;
if(l==r) return;
int mid=l+r>>1;
if(pos<=mid)
update(t[x].lson,t[pre].lson,l,mid,pos,delta);
else
update(t[x].rson,t[pre].rson,mid+1,r,pos,delta);
}
int quek(int x,int l,int r,int k)
{
if(l==r) return l;
int delta=t[t[x].lson].sum,mid=l+r>>1;
if(k<=delta) return quek(t[x].lson,l,mid,k);
else return quek(t[x].rson,mid+1,r,k-delta);
} int quesum(int x,int l,int r,int ql,int qr)
{
if(ql>r||qr<l) return 0;
if(ql<=l&&r<=qr) return t[x].sum;
int mid=l+r>>1;
return quesum(t[x].lson,l,mid,ql,qr)+quesum(t[x].rson,mid+1,r,ql,qr);
} int main()
{
//freopen("test.in","r",stdin);
scanf("%d",&T);
for(int ttt=1;ttt<=T;ttt++)
{
printf("Case #%d:",ttt);
cnt=1;
memset(pos,0,sizeof(pos));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
//build(t[n+1],1,n);//看了yyb的博客我才知道,这题的主席树最开始为空的版本不需要建树,浪费空间。原因是这道题查询的时候是单独查一棵树,而不是查询两棵树后做差。
for(int i=n;i;i--)
{
if(!pos[a[i]]) update(root[i],root[i+1],1,n,i,1),pos[a[i]]=i;
else
{
update(root[i],root[i+1],1,n,i,1);
update(root[i],root[i],1,n,pos[a[i]],-1);
pos[a[i]]=i;
}
}
int ans = 0, l, r;
while(m--)
{
scanf("%d%d",&l,&r);
l=(l+ans)%n+1,r=(r+ans)%n+1;
if (l > r) std::swap(l, r);
int k=quesum(root[l],1,n,l,r);
k=k+1>>1;
printf(" %d",ans=quek(root[l],1,n,k));
}
puts("");
}
return 0;
}

HDU 5919 Sequence ll的更多相关文章

  1. HDU 5919 Sequence II(主席树+逆序思想)

    Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) To ...

  2. HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

    HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...

  3. HDU 5919 Sequence II(可持久化线段树)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5919 [题目大意] 给出一个数列,每次查询数列中,区间非重元素的下标的中位数.查询操作强制在线. [ ...

  4. hdu 5919 Sequence II (可持久化线段树)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919 大致题意: 给你一个长度为n的序列,q个询问,每次询问是给你两个数x,y,经过与上一次的答案进行运算 ...

  5. HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5919 题意:给出一串序列,每次给出区间,求出该区间内不同数的个数k和第一个数出现的位置(将这些位置组 ...

  6. HDU 5919 Sequence II 主席树

    Sequence II Problem Description   Mr. Frog has an integer sequence of length n, which can be denoted ...

  7. HDU 5919 -- Sequence II (主席树)

    题意: 给一串数字,每个数字的位置是这个数第一次出现的位置. 每个询问对于序列的一个子区间,设一共有k个不同的数,求第ceil(k/2)个数的位置. 因为强制在线,所以离线乱搞pass掉. 主席树可解 ...

  8. HDU 5919 Sequence II(主席树)题解

    题意:有A1 ~ An组成的数组,给你l r,L = min((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),R = max((l + ans[ ...

  9. HDU - 5919 Sequence II

    题意: 给定长度为n的序列和q次询问.每次询问给出一个区间(L,R),求出区间内每个数第一次出现位置的中位数,强制在线. 题解: 用主席树从右向左的插入点.对于当前点i,如果a[i]出现过,则把原位置 ...

随机推荐

  1. ubuntu/如何启动、关闭和设置ubuntu防火墙

    由于LInux原始的防火墙工具iptables过于繁琐,所以ubuntu默认提供了一个基于iptable之上的防火墙工具ufw. ubuntu 9.10默认的便是UFW防火墙,它已经支持界面操作了.在 ...

  2. MVC中的cshtml与ASPX的区别

    在MVC3中,即可以使用cshtml,也可以使用aspx, 这两者到底有什么区别呢? 越详细越好,如果是用来正式开发,用哪种比较好. --------------------------------- ...

  3. [DS+Algo] 005 三种简单排序及其代码实现

    目录 1. 冒泡排序 BubbleSort 1.1 算法描述 1.2 性能分析 1.3 Python 代码实现 2. 选择排序 SelectionSort 2.1 算法描述 2.2 选择排序的主要优点 ...

  4. SVN的各种符号含义,svn的星号,感叹号,问号等含义

    黄色感叹号(有冲突):--这是有冲突了,冲突就是说你对某个文件进行了修改,别人也对这个文件进行了修改,别人抢在你提交之前先提交了,这时你再提交就会被提示发生冲突,而不允许你提交,防止你的提交覆盖了别人 ...

  5. Java数据结构之栈(Stack)

    1.栈(Stack)的介绍 栈是一个先入后出(FILO:First In Last Out)的有序列表. 栈(Stack)是限制线性表中元素的插入和删除只能在同一端进行的一种特殊线性表. 允许插入和删 ...

  6. PHP 堆 栈 数据段 代码段 存储的理解

    对象在PHP里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢? 内存从逻辑上说大体上是分为4段,栈空间段.堆空间段 ...

  7. 搜索专题: HDU1016Prime Ring Problem

    Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  8. Proxy does not work using sudo in Debian

    To resolve this issue you can add Defaults env_keep += "http_proxy https_proxy" to your /e ...

  9. Linux中设置别名alias永久生效

    现在有个项目目录位于/var/www/html/tp5下 这也是我经常用到的工作目录 为了避免每次进入此目录 都需要输入 cd /var/www/html/tp5 可以加上述命令加入别名 alias ...

  10. Window Operations详解

    window(windowLength, slideInterval):返回窗口长度为windowLength,每隔slideInterval滑动一次的window DStream countByWi ...