JZOJ-senior-5933. 【NOIP2018模拟10.27】百鸽笼

Time Limits: 2000 ms Memory Limits: 262144 KB

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。

Solution

  • 在前端加入删除,那就反过来啊
  • 动态查询区间第K小,那就上主席树啊
  • 真是简单又自然,难得在比赛场上我这种菜鸡能切掉一题

Code

#include<algorithm>
#include<cstdio>
#include<cctype>

#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#define P(c) putchar(c)

using namespace std;

const int N=4e5+5,M=128e5+5,MX=1e9;
int n,m,t,v,L,R,K,tot,cnt;
int a[N],rt[N];
struct tree{int l,r,s;}tr[M];

inline void read(int &n)
{
	int x=0,w=0; char ch=0;
	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	n=w?-x:x;
}

inline void write(int x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10+'0');
}

void ins(int x,int l,int r,int p)
{
	if(l==r) return;
	int mid=(l+r)>>1;
	if(p<=mid)
	{
		int y=tr[x].l;
		tr[++tot]=(tree){tr[y].l,tr[y].r,tr[y].s+1};
		tr[x].l=tot,ins(tr[x].l,l,mid,p);
	}
	else
	{
		int y=tr[x].r;
		tr[++tot]=(tree){tr[y].l,tr[y].r,tr[y].s+1};
		tr[x].r=tot,ins(tr[x].r,mid+1,r,p);
	}
}

void ask(int x,int y,int l,int r,int p)
{
	if(l==r) {write(l),P('\n'); return;}
	int mid=(l+r)>>1;
	int lx=tr[x].l,ly=tr[y].l;
	int rx=tr[x].r,ry=tr[y].r;
	if(tr[ly].s-tr[lx].s>=p) ask(lx,ly,l,mid,p);
		else ask(rx,ry,mid+1,r,p-(tr[ly].s-tr[lx].s));
}

int main()
{
	freopen("pigeon.in","r",stdin);
	freopen("pigeon.out","w",stdout);
	read(n),read(m),tot=cnt=n;
	fo(i,1,n) read(a[i]);
	fo(i,1,n/2) swap(a[i],a[n-i+1]);
	fo(i,1,n)
	{
		tr[i]=(tree){tr[i-1].l,tr[i-1].r,tr[i-1].s+1};
		rt[i]=i,ins(i,1,MX,a[i]);
	}
	fo(i,1,m)
	{
		read(t);
		if(t==1) --cnt;
		if(t==2)
		{
			read(v);
			int lst=rt[cnt];
			rt[++cnt]=++tot;
			tr[tot]=(tree){tr[lst].l,tr[lst].r,tr[lst].s+1};
			ins(tot,1,MX,v);
		}
		if(t==3)
		{
			read(L),read(R),read(K);
			int opl=cnt-R+1,opr=cnt-L+1;
			ask(rt[opl-1],rt[opr],1,MX,K);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值