1. 程式人生 > >【JZOJ A組】百鴿籠

【JZOJ A組】百鴿籠

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);
		}
	}
}