题目链接:http://www.ifrog.cc/acm/problem/1157
1157 - 造物主的戒律
Time Limit:20s Memory Limit:512MByte
Submissions:681Solved:69
DESCRIPTION
造物主的戒律,空气,变成数据结构!
于是空气变成了数据结构~
给你一个序列,每次查询区间中小于等于x的所有数字里面第k1k1小的值以及大于x的所有数字里面第k2k2小的值,如果不存在,输出-1
每次输出两个数,对于每个数如果不存在,则单独输出-1
INPUT
第一行两个数n,m
第二行n个数表示序列a
后面m行每行五个数l,r,x,k1,k2
OUTPUT
对于每个查询输出答案
SAMPLE INPUT
5 5
1 2 3 4 5
1 5 3 1 2
2 5 2 1 3
2 3 3 3 3
3 3 3 3 3
3 3 3 3 3
SAMPLE OUTPUT
1 5
2 5
-1 -1
-1 -1
-1 -1
HINT
n,m<= 400000 ,0 <= a[i] <= 1000000000
大家想知道这游戏叫什么吗
叫liber7
这个叫由乃的
真的有毒。
——来自另一个出题人。
----------------------
484觉得图多。
我会告诉你我删了好多张了么。
当然会,图好多还超级大。
我都给它缩小了。
——来自一个上题人
SOLUTION
思路:主席树模板题;
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<bitset> #include<set> #include<map> using namespace std; #define LL long long #define pi (4*atan(1.0)) #define eps 1e-8 #define bug(x) cout<<"bug"<<x<<endl; const int N=8e5+100,M=1e6+10,inf=1e9+10; const LL INF=1e18+10,mod=998244353; struct Chairmantree { int rt[N*20],ls[N*20],rs[N*20],sum[N*20]; int tot; void init() { tot=0; memset(ls,0,sizeof(ls)); memset(rs,0,sizeof(rs)); memset(sum,0,sizeof(sum)); memset(rt,0,sizeof(rt)); } void build(int l,int r,int &pos) { pos=++tot; sum[pos]=0; if(l==r)return; int mid=(l+r)>>1; build(l,mid,ls[pos]); build(mid+1,r,rs[pos]); } void update(int p,int c,int pre,int l,int r,int &pos) { pos=++tot; ls[pos]=ls[pre]; rs[pos]=rs[pre]; sum[pos]=sum[pre]+c; if(l==r)return; int mid=(l+r)>>1; if(p<=mid) update(p,c,ls[pre],l,mid,ls[pos]); else update(p,c,rs[pre],mid+1,r,rs[pos]); } int rank(int s,int e,int L,int R,int l,int r) { if(L<=l&&r<=R)return sum[e]-sum[s]; int mid=(l+r)>>1; int ans=0; if(L<=mid) ans+=rank(ls[s],ls[e],L,R,l,mid); if(R>mid) ans+=rank(rs[s],rs[e],L,R,mid+1,r); return ans; } int query(int L,int R,int l,int r,int k) { if(l==r)return l; int mid=(l+r)>>1; int num=sum[ls[R]]-sum[ls[L]]; if(k<=num)return query(ls[L],ls[R],l,mid,k); else return query(rs[L],rs[R],mid+1,r,k-num); } }; Chairmantree tree; int a[N],b[N]; struct is { int l,r,k1,k2,x; }q[N]; int getpos(int x,int cnt) { int pos=lower_bound(b+1,b+cnt,x)-b; return pos; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=a[i]; } for(int i=1;i<=m;i++) { scanf("%d%d%d%d%d",&q[i].l,&q[i].r,&q[i].x,&q[i].k1,&q[i].k2); b[n+i]=q[i].x; } sort(b+1,b+1+n+m); int num=unique(b+1,b+1+n+m)-b; tree.init(); tree.build(1,num-1,tree.rt[0]); for(int i=1;i<=n;i++) { int p=getpos(a[i],num); tree.update(p,1,tree.rt[i-1],1,num-1,tree.rt[i]); } //for(int i=1;i<num;i++) // printf("%d ",tree.rt[i]); //printf(" "); for(int i=1;i<=m;i++) { int l=q[i].l,r=q[i].r,x=q[i].x,k1=q[i].k1,k2=q[i].k2; int p1=getpos(x,num); int p=tree.rank(tree.rt[l-1],tree.rt[r],1,p1,1,num-1); //cout<<"xxx "<<p<<" "<<num-1<<endl; int ans1=-1,ans2=-1; if(p>=k1)ans1=tree.query(tree.rt[l-1],tree.rt[r],1,num-1,k1); if(p+k2<=(r-l+1))ans2=tree.query(tree.rt[l-1],tree.rt[r],1,num-1,p+k2); //printf("%d ",b[tree.query(tree.rt[l-1],tree.rt[r],1,num-1,k)]); if(ans1!=-1)printf("%d ",b[ans1]); else printf("-1 "); if(ans2!=-1)printf("%d ",b[ans2]); else printf("-1 "); } } return 0; }