Description
Input
从文件 pigeon.in 中读入数据。
输入第一行包含两个正整数 n, m ,分别表示初始鸽笼数与操作个数。
第二行包含 n 个正整数,第 i 个数表示从左往右第 i 个初始鸽笼中鸽子的咕咕能力值 vi 。
接下去 m 行每行表示一个操作。操作输入格式见题面描述。
Output
输出到文件 pigeon.out 中。
输出包含若干行,每行表示一个相应的 3 操作的答案。
Sample Input
6 8
2 7 4 3 5 9
3 2 5 3
1
2 4
3 1 4 2
2 6
3 1 7 5
1
3 3 6 4
Sample Output
5
4
6
9
Data Constraint
题目更正:vi值域小于等于1e9。
思路
把序列倒过来,建一棵线段树即可
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn 400077
#define inf 1000000000
using namespace std;
int n,m,ans,cnt,k[maxn],v[maxn];
struct T{int v,l,r;}tr[maxn*31];
void add(int &d,int l,int r,int x)
{
tr[++cnt]=tr[d],tr[d=cnt].v++;
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) add(tr[d].l,l,mid,x); else add(tr[d].r,mid+1,r,x);
}
void query(int l,int r,int st,int ed,int x)
{
if (st==ed) { ans=st; return; }
int mid=(st+ed)>>1;
if (x<=tr[tr[l].l].v-tr[tr[r].l].v) query(tr[l].l,tr[r].l,st,mid,x);
else query(tr[l].r,tr[r].r,mid+1,ed,x-tr[tr[l].l].v+tr[tr[r].l].v);
}
int main()
{
freopen("pigeon.in","r",stdin),freopen("pigeon.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) scanf("%d",&v[i]);
for(int i=1; i<=n/2; i++) swap(v[i],v[n-i+1]);
for(int i=1; i<=n; i++) k[i]=k[i-1],add(k[i],0,inf,v[i]);
for(int i=1,num,x,l,r; i<=m; i++)
{
scanf("%d",&num);
if (num==1) n--;
if (num==2) scanf("%d",&x),k[++n]=k[n-1],add(k[n],0,inf,x);
if (num==3)
{
scanf("%d%d%d",&l,&r,&x),swap(l,r);
l=n-l+1,r=n-r+1,query(k[r],k[l-1],0,inf,x);
printf("%d\n",ans);
}
}
}