博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[国家集训队2012]middle
阅读量:7069 次
发布时间:2019-06-28

本文共 3320 字,大约阅读时间需要 11 分钟。

 

二分答案x

把区间内>=x的数设为1,<x的数设为-1

左端点在[a,b]之间,右端点在[c,d]之间的子序列中,若中位数>=x,

那么 [b+1,c-1]的区间和+[a,b]的最大右子段和+[c,d]的最大左子段和>=0

查询可以用线段树

多组询问,不能每一次二分都重设1和-1

所以用主席树

其中第i棵线段树表示<=i的都被设成了-1

因为主席树是线段树的前缀和,所以一次修改只需要改第i棵线段树,就可以得到<=i的都被设成-1的线段树

 

#include
#include
#include
#define N 20001using namespace std;int n;pair
a[N];int cnt;int root[N],lc[N*20],rc[N*20];int q[4];struct node{ int sum,lmax,rmax; node operator + (node p) { node c; c.sum=sum+p.sum; c.lmax=max(lmax,sum+p.lmax); c.rmax=max(p.rmax,rmax+p.sum); return c; } }e[N*20],zero;void read(int &x){ x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }}void build(int &k,int l,int r){ k=++cnt; if(l==r) { e[k].sum=e[k].lmax=e[k].rmax=1; return; } int mid=l+r>>1; build(lc[k],l,mid); build(rc[k],mid+1,r); e[k]=e[lc[k]]+e[rc[k]];}void change(int pre,int &k,int l,int r,int pos){ k=++cnt; if(l==r) { e[k].sum=e[k].lmax=e[k].rmax=-1; return; } int mid=l+r>>1; if(pos<=mid) { rc[k]=rc[pre]; change(lc[pre],lc[k],l,mid,pos); } else { lc[k]=lc[pre]; change(rc[pre],rc[k],mid+1,r,pos); } e[k]=e[lc[k]]+e[rc[k]];}node query(int k,int l,int r,int opl,int opr){ if(opl>opr) return zero; if(l>=opl && r<=opr) return e[k]; int mid=l+r>>1; if(opr<=mid) return query(lc[k],l,mid,opl,opr); if(opl>mid) return query(rc[k],mid+1,r,opl,opr); return query(lc[k],l,mid,opl,opr)+query(rc[k],mid+1,r,opl,opr);}bool check(int pos){ if(query(root[pos],1,n,q[0],q[1]).rmax+query(root[pos],1,n,q[1]+1,q[2]-1).sum+query(root[pos],1,n,q[2],q[3]).lmax>=0) return true; return false;}int main(){ freopen("nt2012_middle.in","r",stdin); freopen("nt2012_middle.out","w",stdout); read(n); for(int i=1;i<=n;++i) { read(a[i].first); a[i].second=i; } sort(a+1,a+n+1); build(root[0],1,n); for(int i=1;i<=n;++i) change(root[i-1],root[i],1,n,a[i].second); int m; read(m); int ans=0; int l,r,mid; while(m--) { for(int i=0;i<4;++i) { read(q[i]); q[i]+=ans; q[i]%=n; q[i]++; } sort(q,q+4); l=0,r=n; while(l<=r) { mid=l+r>>1; if(check(mid-1)) ans=mid,l=mid+1; else r=mid-1; } ans=a[ans].first; cout<
<<'\n'; }}

 

1763. [国家集训队2012]middle

★★★☆   输入文件:nt2012_middle.in   输出文件:nt2012_middle.out   简单对比

时间限制:3 s   内存限制:1024 MB

middle(陈立杰)
时间限制:3.0s   内存限制:1.0GB

【大意】

一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。
位置也从0开始标号。
我会使用一些方式强制你在线。

【输入格式】

第一行序列长度n。
接下来n行按顺序给出a中的数。
接下来一行Q。
然后Q行每行a,b,c,d,我们令上个询问的答案是x(如果这是第一个询问则x=0)。
令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
将q从小到大排序之后,令真正的要询问的a=q[0],b=q[1],c=q[2],d=q[3]。
输入保证满足条件。

【输出格式】

Q行依次给出询问的答案。

【数据规模和约定】

0:n,Q<=100
1,...,5:n<=2000
0,...,19:n<=20000,Q<=25000

【样例输入】

5
170337785
271451044
22430280
969056313
206452321
3
3 1 0 2
2 3 1 4
3 1 4 0

【样例输出】

271451044
271451044
969056313

 

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/8193829.html

你可能感兴趣的文章
切换RequiredFieldValidator和RegularExpressionValidator提示信息的控件
查看>>
基于类的封装[基础]
查看>>
android studio插件提升工作效率
查看>>
What is VMR(Video Mixing Render)-From MSDN
查看>>
Linux下安装nmap扫描工具
查看>>
git 创建branch分支【转】
查看>>
北京某公司.NET面试题
查看>>
解决异常“SqlParameterCollection 只接受非空的 SqlParameter 类型对象。”
查看>>
PostgreSQL通过mysql_fdw访问MySQL数据库
查看>>
REST风格的原则
查看>>
Struts分页的一个实现
查看>>
[LintCode] Nuts & Bolts Problem 螺栓螺母问题
查看>>
53.2. group_concat() 列传行
查看>>
I.MX6 SHT20 Linux 驱动移植
查看>>
7.4. String
查看>>
使用PHP配置文件
查看>>
【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
查看>>
开发网站合集
查看>>
fastcgi配置
查看>>
[转]Java中堆和栈创建对象的区别
查看>>