[Zjoi2013] K large number query-tree set tree

topic

[Zjoi2013]K large number query

answer

The idea of ​​the question is probably to give you n vectors, insert and query a number of consecutively numbered vectors.

Typical tree set tree chant

First build a line segment tree for all inserted c values, and then maintain a line segment tree for each node. The line segment tree of the leaf node stores the distribution of the value in the sequence (that is, the value in each vector in the sequence The number of occurrences, maintenance interval and), the line segment tree of the parent node stores the distribution of all c values ​​in the limited interval in the sequence, that is, the line segment trees of all child nodes are merged.

Insertion is to modify the large line segment tree at a single point, and add interval to each small line segment tree on the chain;

The query is to use the big line segment tree to make a binary answer, and each time the small line segment tree is searched for interval, the total complexity is O(n\log^2n).

The code size of the tree set tree is well-deserved. Fortunately, I play the board beautifully and less debugging.

Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#define ll long long
#define MAXN 50005
#define MAXP 20000005
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n;

struct itn{    //小线段树
	int ls,rs,lz;ll a;
	itn(){ls=rs=lz=a=0;}
}t[MAXP];
int IN;
inline void pushd(int x,int l,int r){
	if(t[x].lz>0){
		if(l==r){t[x].lz=0;return;}
		int mid=(l+r)>>1;
		if(!t[x].ls)t[x].ls=++IN,t[IN]=itn();
		t[t[x].ls].a+=(1ll+mid-l)*t[x].lz,t[t[x].ls].lz+=t[x].lz;
		if(!t[x].rs)t[x].rs=++IN,t[IN]=itn();
		t[t[x].rs].a+=(0ll+r-mid)*t[x].lz,t[t[x].rs].lz+=t[x].lz;
		t[x].lz=0;
	}
}
inline void addt(int x,int l,int r,int a,int b){
	if(l==a&&r==b){
		t[x].a+=r-l+1,t[x].lz++;
		return;
	}
	int mid=(l+r)>>1;pushd(x,l,r);
	if(a<=mid){
		if(!t[x].ls)t[x].ls=++IN,t[IN]=itn();
		addt(t[x].ls,l,mid,a,min(b,mid));
	}
	if(b>mid){
		if(!t[x].rs)t[x].rs=++IN,t[IN]=itn();
		addt(t[x].rs,mid+1,r,max(a,mid+1),b);
	}
	t[x].a=t[t[x].ls].a+t[t[x].rs].a;
}
inline ll sch(int x,int l,int r,int a,int b){
	if(!x)return 0;
	if(l==a&&r==b)return t[x].a;
	int mid=(l+r)>>1;pushd(x,l,r);
	ll res=0;
	if(a<=mid)res+=sch(t[x].ls,l,mid,a,min(b,mid));
	if(b>mid)res+=sch(t[x].rs,mid+1,r,max(a,mid+1),b);
	return res;
}

struct ITN{    //大线段树
	int ls,rs,id;
}tr[MAXN<<4];
int NN;
inline void add(int x,int l,int r,int a,int b,int z){
	if(l==r){addt(tr[x].id,1,n,a,b);return;}
	int mid=(l+r)>>1;
	if(z<=mid){
		if(!tr[x].ls)tr[x].ls=++NN,tr[tr[x].ls].id=++IN,t[IN]=itn();
		add(tr[x].ls,l,mid,a,b,z);
	}
	else{
		if(!tr[x].rs)tr[x].rs=++NN,tr[tr[x].rs].id=++IN,t[IN]=itn();
		add(tr[x].rs,mid+1,r,a,b,z);
	}
	addt(tr[x].id,1,n,a,b);
}
inline int query(int x,int l,int r,int a,int b,ll c){
	if(l==r)return l;
	int mid=(l+r)>>1;ll z=sch(tr[tr[x].rs].id,1,n,a,b);
	if(z>=c)return query(tr[x].rs,mid+1,r,a,b,c);
	else return query(tr[x].ls,l,mid,a,b,c-z);
}

signed main()
{
	n=read();
	tr[++NN].id=++IN;
	for(int M=read();M--;){
		int opt=read(),a=read(),b=read();ll c=read();
		if(opt==1)add(1,-n,n,a,b,c);
		else printf("%d\n",query(1,-n,n,a,b,c));
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/weixin_43960287/article/details/113827132