P3332-[ZJOI2013]K大数查询【树套树】

正题

题目链接:https://www.luogu.com.cn/problem/P3332


题目大意

开始 n n 个可以重复的集合,要求支持操作

  1. 1   l   r   c : 1\ l\ r\ c: c c 加入集合 l r l\sim r
  2. 2   l   r   k : 2\ l\ r\ k: 查询 l r l\sim r 的并集中第 k k 大的数

解题思路

此题考验选手的卡常能力(

维护一个树套树,外面是一个权值线段树,然后每个节点套一个区间线段树。然后每次询问和修改的时候就只用使用该节点的线段树的 l r l\sim r 段即可。

然后区间线段树需要临时开点(废话

之后卡常的话用固定标记,标记不下传,查询的时候再根据沿路的标记来计算答案即可。


c o d e code

#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
%:pragma GCC optimize("-fgcse")
%:pragma GCC optimize("-fgcse-lm")
%:pragma GCC optimize("-fipa-sra")
%:pragma GCC optimize("-ftree-pre")
%:pragma GCC optimize("-ftree-vrp")
%:pragma GCC optimize("-fpeephole2")
%:pragma GCC optimize("-ffast-math")
%:pragma GCC optimize("-fsched-spec")
%:pragma GCC optimize("unroll-loops")
%:pragma GCC optimize("-falign-jumps")
%:pragma GCC optimize("-falign-loops")
%:pragma GCC optimize("-falign-labels")
%:pragma GCC optimize("-fdevirtualize")
%:pragma GCC optimize("-fcaller-saves")
%:pragma GCC optimize("-fcrossjumping")
%:pragma GCC optimize("-fthread-jumps")
%:pragma GCC optimize("-funroll-loops")
%:pragma GCC optimize("-fwhole-program")
%:pragma GCC optimize("-freorder-blocks")
%:pragma GCC optimize("-fschedule-insns")
%:pragma GCC optimize("inline-functions")
%:pragma GCC optimize("-ftree-tail-merge")
%:pragma GCC optimize("-fschedule-insns2")
%:pragma GCC optimize("-fstrict-aliasing")
%:pragma GCC optimize("-fstrict-overflow")
%:pragma GCC optimize("-falign-functions")
%:pragma GCC optimize("-fcse-skip-blocks")
%:pragma GCC optimize("-fcse-follow-jumps")
%:pragma GCC optimize("-fsched-interblock")
%:pragma GCC optimize("-fpartial-inlining")
%:pragma GCC optimize("no-stack-protector")
%:pragma GCC optimize("-freorder-functions")
%:pragma GCC optimize("-findirect-inlining")
%:pragma GCC optimize("-fhoist-adjacent-loads")
%:pragma GCC optimize("-frerun-cse-after-loop")
%:pragma GCC optimize("inline-small-functions")
%:pragma GCC optimize("-finline-small-functions")
%:pragma GCC optimize("-ftree-switch-conversion")
%:pragma GCC optimize("-foptimize-sibling-calls")
%:pragma GCC optimize("-fexpensive-optimizations")
%:pragma GCC optimize("-funsafe-loop-optimizations")
%:pragma GCC optimize("inline-functions-called-once")
%:pragma GCC optimize("-fdelete-null-pointer-checks")
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define rint register int
using namespace std;
const int M=5e4+10,N=(5e4)*400+10;
int n,m,tot,cnt,b[M],op[M],l[M],r[M],a[M];
int ls[N],rs[N],lazy[N],root[M*2];
ll val[N];
char buf[1<<23],*head=buf;//fread优化
inline int read(){
    int x=0,y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
template<typename T>
inline T read(){
    T x=0;
    int y=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return y?-x:x;
}
void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10+48);
}
inline void updata(int &x,int l,int r,int L=1,int R=n){
	if(!x)x=++cnt;
	val[x]+=(ll)(min(R,r)-max(L,l)+1);
	if(l<=L&&R<=r){
		lazy[x]++;
		return;
	}
	rint mid=(L+R)>>1;
	if(mid>=l)updata(ls[x],l,r,L,mid);
	if(r>mid)updata(rs[x],l,r,mid+1,R);
	return;
}
inline ll ask(int &x,int l,int r,int L=1,int R=n,ll t=0){
	if(!x) return (ll)(min(R,r)-max(L,l)+1)*t;
	if(l<=L&&R<=r)
		return val[x]+1ll*(min(R,r)-max(L,l)+1)*t;
	rint mid=(L+R)>>1;
	ll ans=0;
	if(mid>=l)ans+=ask(ls[x],l,r,L,mid,t+lazy[x]);
	if(r>mid)ans+=ask(rs[x],l,r,mid+1,R,t+lazy[x]);
	return ans;
}
inline void change(int l,int r,int pos,int L=1,int R=tot,int x=1){
	updata(root[x],l,r);
	if(L==R)return;
	rint mid=(L+R)>>1;
	if(pos<=mid)change(l,r,pos,L,mid,x<<1);
	else change(l,r,pos,mid+1,R,x<<1|1);
	return;
}
inline int query(int l,int r,ll k,int L=1,int R=tot,int x=1){
	if(L==R)return b[L];
	rint mid=(L+R)>>1;
	ll z=ask(root[x<<1|1],l,r);
	if(z<k)return query(l,r,k-z,L,mid,x<<1);
	return query(l,r,k,mid+1,R,x<<1|1);
}
int main()
{
	freopen("P3332_6.in","r",stdin);
	freopen("P3332_6.ans","w",stdout); 
	n=read();m=read();
	for(rint i=1;i<=m;i++){
		op[i]=read();l[i]=read();
		r[i]=read();a[i]=read();
		if(op[i]==1)b[++tot]=a[i];
	}
	sort(b+1,b+1+tot);
	tot=unique(b+1,b+1+tot)-b-1;
	for(rint i=1;i<=m;i++){
		if(op[i]==1)
			a[i]=lower_bound(b+1,b+1+tot,a[i])-b,
			change(l[i],r[i],a[i]);
		if(op[i]==2)
			print(query(l[i],r[i],a[i])),putchar('\n');
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/106025384