主席树(可持续化线段树)

入门的一篇讲解,很棒:http://www.mamicode.com/info-detail-2600077.html
题目练习:https://blog.csdn.net/qq_34940287/article/details/87718729

K-th Number

Poj 2104
查询区间第k小

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010;

inline int read()
{
	int res=0;
	char ch;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9') res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
	return res; 
}
int ls[maxn*20],rs[maxn*20],sum[maxn*20],root[maxn]; 
int n,m,a[maxn],b[maxn],cnt;

void update(int &now,int old,int l,int r,int pos)
{
	now=++cnt;
	ls[now]=ls[old];rs[now]=rs[old];
	sum[now]=sum[old]+1;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(pos<=mid) update(ls[now],ls[old],l,mid,pos);
	else update(rs[now],rs[old],mid+1,r,pos); 
}
int query(int x,int y,int l,int r,int val)
{
	if(l==r) return l;
	int c=sum[ls[y]]-sum[ls[x]];
	int mid=(l+r)>>1;
	if(val<=c) return query(ls[x],ls[y],l,mid,val);
	else return query(rs[x],rs[y],mid+1,r,val-c);
}

int main()
{
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
		sort(b+1,b+n+1);
		int sz=unique(b+1,b+n+1)-b-1;
		int l,r,x;
		cnt=0;
		for(int i=1;i<=n;i++){
			int pos=lower_bound(b+1,b+sz+1,a[i])-b;//
			update(root[i],root[i-1],1,sz,pos);
		}
		for(int i=0;i<m;i++){
			scanf("%d%d%d",&l,&r,&x);
			int ans=b[query(root[l-1],root[r],1,sz,x)];
			printf("%d\n",ans);
		}
	}
	return 0;
}
/*
7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3

*/

Count on a tree(可持续化线段树(主席树)树上第k小)

SPOJ - COT
题意:给定一棵树,q个查询,求路径u-v上第k小
参考代码:https://blog.csdn.net/qq_41730082/article/details/86652202

#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=100010;

struct edge{
	int nxt,v;
}e[maxn*2];
int head[maxn],tot;
int n,m,a[maxn],b[maxn],num;
int f[maxn][20],deep[maxn];
int order,tree[maxn],lson[maxn*20],rson[maxn*20],sz[maxn*20];
inline void init()
{
	memset(head,-1,sizeof(head));
	order=tot=0;
	memset(f,-1,sizeof(f));
}
void addedge(int u,int v)
{
	e[tot].v=v;e[tot].nxt=head[u];
	head[u]=tot++;
}
void dfs(int u,int pre,int d)
{
	f[u][0]=pre;
	deep[u]=d;
	for(int i=head[u];~i;i=e[i].nxt){
		int v=e[i].v;
		if(v==pre) continue;
		dfs(v,u,d+1);
	}
}
void pre_lca()
{
	dfs(1,0,0);
	for(int j=0;(1<<(j+1))<n;j++){
		for(int i=1;i<=n;i++){
			if(f[i][j]<0) f[i][j+1]=-1;
			else f[i][j+1]=f[f[i][j]][j];
		}
	}
}
int get_lca(int x,int y)
{
	if(deep[x]<deep[y]) swap(x,y);
	int det=deep[x]-deep[y];
	for(int i=0;(1<<i)<=det;i++) if(det&(1<<i)) x=f[x][i];
	if(x==y) return x;
	for(int i=log2(1.0*n);i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];y=f[y][i];
		}
	}
	return f[x][0];
}
void build(int &k,int l,int r)
{
	k=++order;
	sz[k]=0;
	if(l==r) return;
	int m=(l+r)>>1;
	build(lson[k],l,m);
	build(rson[k],m+1,r);
}
void update(int old,int &now,int l,int r,int qx)
{
	now=++order;
	lson[now]=lson[old];rson[now]=rson[old];sz[now]=sz[old]+1;
	if(l==r) return;
	int m=(l+r)>>1;
	if(qx<=m) update(lson[old],lson[now],l,m,qx);
	else update(rson[old],rson[now],m+1,r,qx);
}
int query(int i,int j,int l,int r,int k,int lca,int fsa)
{
	if(l==r) return l;
	int det=sz[lson[i]]+sz[lson[j]]-sz[lson[lca]]-sz[lson[fsa]];
	int m=(l+r)>>1;
	if(k<=det) return query(lson[i],lson[j],l,m,k,lson[lca],lson[fsa]);
	else return query(rson[i],rson[j],m+1,r,k-det,rson[lca],rson[fsa]);
}
void dfs_build(int u,int pre)
{
	int pos=(int)(lower_bound(b+1,b+num+1,a[u])-b);
	update(tree[pre],tree[u],1,num,pos);
	for(int i=head[u];~i;i=e[i].nxt){
		int v=e[i].v;
		if(v==pre) continue;
		dfs_build(v,u);
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m)){
		init();
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);b[i]=a[i];
		}
		sort(b+1,b+n+1);
		num=unique(b+1,b+n+1)-b-1;
		int u,v;
		for(int i=1;i<n;i++){
			scanf("%d%d",&u,&v);
			addedge(u,v);addedge(v,u);
		}
		pre_lca();
		build(tree[0],1,num);
		dfs_build(1,0);
		for(int i=1;i<=m;i++){
			int l,r,k;scanf("%d%d%d",&l,&r,&k);
			int lca=get_lca(l,r);
			int pos=query(tree[l],tree[r],1,num,k,tree[lca],tree[f[lca][0]]);
			printf("%d\n",b[pos]);
		}
	}
	return 0;
}

最大异或和

Bzoj 3261
题解:http://hzwer.com/5634.html

#include<bits/stdc++.h>
using namespace std;
const int maxn=600010;

inline int read()
{
	int res=0;
	char ch;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9') res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
	return res; 
}
int bin[30];
int n,m;
int a[maxn],b[maxn],root[maxn];
struct Trie{
	int cnt;
	int ch[maxn*24][2],sum[maxn*24];
	int insert(int x,int val){
		int tmp,y;tmp=y=++cnt;
		for(int i=23;i>=0;i--){
			ch[y][0]=ch[x][0];ch[y][1]=ch[x][1];
			sum[y]=sum[x]+1;
			int t=val&bin[i];t>>=i;
			x=ch[x][t];
			ch[y][t]=++cnt;
			y=ch[y][t];
		}
		sum[y]=sum[x]+1;
		return tmp;
	}
	int query(int l,int r,int val){
		int tmp=0;
		for(int i=23;i>=0;i--){
			int t=val&bin[i];t>>=i;
			if(sum[ch[r][t^1]]-sum[ch[l][t^1]])
				tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1];
			else r=ch[r][t],l=ch[l][t];
		}
		return tmp;
	}
}trie;
int main()
{
	bin[0]=1;
	for(int i=1;i<30;i++) bin[i]=bin[i-1]<<1;
	n=read();m=read();
	n++;
	for(int i=2;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++) b[i]=b[i-1]^a[i];
	for(int i=1;i<=n;i++)
		root[i]=trie.insert(root[i-1],b[i]);
	char ch[4];
	int l,r,x;
	while(m--){
		scanf("%s",ch);
		if(ch[0]=='A'){
			n++;a[n]=read();b[n]=b[n-1]^a[n];
			root[n]=trie.insert(root[n-1],b[n]);
		}else{
			l=read();r=read();x=read();
			printf("%d\n",trie.query(root[l-1],root[r],b[n]^x));
		}
	}
	return 0;
}
/*
5 5
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
*/

[POI2014]KUR-Couriers

P3567
题意是嫖的:https://www.cnblogs.com/winmt/p/6607392.html
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=5000010;

int sum[maxn*20],ls[maxn*20],rs[maxn*20];
int root[maxn],n,m,cnt;

void update(int &now,int old,int l,int r,int pos)
{
	now=++cnt;
	sum[now]=sum[old]+1;
	if(l==r) return;
	ls[now]=ls[old];rs[now]=rs[old];
	int mid=(l+r)>>1;
	if(pos<=mid) update(ls[now],ls[old],l,mid,pos);
	else update(rs[now],rs[old],mid+1,r,pos);
}
int query(int x,int y,int l,int r,int val)
{
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(sum[ls[y]]-sum[ls[x]]>val) return query(ls[x],ls[y],l,mid,val);
	if(sum[rs[y]]-sum[rs[x]]>val) return query(rs[x],rs[y],mid+1,r,val);
	return 0;
}
int main()
{
	while(~scanf("%d%d",&n,&m)){
		int l,r,x;
		cnt=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&x);
			update(root[i],root[i-1],1,n,x);
		}
		while(m--){
			scanf("%d%d",&l,&r);
			int ans=query(root[l-1],root[r],1,n,(r-l+1)/2);
			printf("%d\n",ans);
		}
	}
}

[CQOI2015]任务查询系统

P3168
参考:https://www.cnblogs.com/TheRoadToTheGold/p/6366165.html
题意:n个任务,给定持续时间s,e以及优先级p;m次查询,查询第x个时间上前k小优先级之和。
题解:以时间建立n棵线段树,线段树上以优先级维护优先级之和,以及优先级数量;优先级要离散化。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=200010;

int ls[maxn*20],rs[maxn*20],num[maxn*20];
ll sum[maxn*20];
int root[maxn],n,m,cnt;
int b[maxn],p[maxn];
struct node{
	int pos,co,val;
}a[maxn];
bool cmp(const node &x,const node &y)
{
	return x.pos<y.pos;
}
int tot;
void init()
{
	sort(b+1,b+2*n+1);
	tot=unique(b+1,b+2*n+1)-b-1;
	for(int i=1;i<=n;i++){
		p[i]=lower_bound(b+1,b+tot+1,p[i])-b;
		a[i*2-1].val=a[i*2].val=p[i];
	}
}
void update(int &now,int old,int l,int r,int w,int c)
{
	now=++cnt;
	sum[now]=sum[old]+1LL*b[w]*c;
	num[now]=num[old]+c;//不是 + 1 
	ls[now]=ls[old];rs[now]=rs[old];
	if(l==r) return;
	int mid=(l+r)>>1;
	if(w<=mid) update(ls[now],ls[old],l,mid,w,c);
	else update(rs[now],rs[old],mid+1,r,w,c);
}
ll query(int x,int l,int r,int k)
{
	if(l==r){
		if(num[x]==0) return 0;
		return sum[x]/num[x]*k;
	}
	int mid=(l+r)>>1;
	if(k<=num[ls[x]]) return query(ls[x],l,mid,k);
	return query(rs[x],mid+1,r,k-num[ls[x]])+sum[ls[x]]; 
}
int main()
{
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;i++){
			scanf("%d%d%d",&a[i*2-1].pos,&a[i*2].pos,&p[i]);
			a[i*2].pos++;
			b[i]=p[i];
			a[i*2-1].co=1;a[i*2].co=-1;
		}

		init();
		sort(a,a+2*n+1,cmp);
		cnt=0;

		memset(sum,0,sizeof(sum));
		memset(num,0,sizeof(num));
		for(int i=1,j=1;i<=m;i++){
			root[i]=root[i-1];//
			while(j<=2*n&&a[j].pos==i){
				update(root[i],root[i],1,tot,a[j].val,a[j].co);
				j++;
			}
		}

		int x,a,b,c,k;
		ll pre=1;
		for(int i=1;i<=m;i++){
			scanf("%d%d%d%d",&x,&a,&b,&c);
			k=1+(1LL*a*pre+b)%c;
			pre=query(root[x],1,tot,k);
			printf("%lld\n",pre);
		}
	}
	return 0; 
}

可持续化数组

可持续化数组板子题:https://www.luogu.org/problem/P3919
参考代码:https://blog.csdn.net/chenxiaoran666/article/details/81503323

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000010;

int n,q,a[maxn],rt[maxn],cnt;
int val[maxn*20],ls[maxn*20],rs[maxn*20];

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void build(int &now,int l,int r)
{
	now=++cnt;
	int mid=(l+r)>>1;
	if(l==r){
		val[now]=a[l];return;
	}
	build(ls[now],l,mid);build(rs[now],mid+1,r);
}
void update(int &now,int old,int l,int r,int x,int y)
{
	now=++cnt;
	val[now]=val[old];
	ls[now]=ls[old];rs[now]=rs[old];
	if(l==r){
		val[now]=y;return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(ls[now],ls[old],l,mid,x,y);
	else update(rs[now],rs[old],mid+1,r,x,y);
}
int query(int now,int l,int r,int x)
{
	int mid=(l+r)>>1;
	if(l==r) return val[now];
	if(x<=mid) return query(ls[now],l,mid,x) ;
	else return query(rs[now],mid+1,r,x);
}
int main()
{
	n=read();q=read();
	for(int i=1;i<=n;++i) a[i]=read();
	cnt=0;
	build(rt[0],1,n);
	int v,op,x,y;
	for(int i=1;i<=q;i++){
		v=read();op=read();x=read();
		if(op==1) y=read(),update(rt[i],rt[v],1,n,x,y);
		else printf("%d\n",query(rt[i]=rt[v],1,n,x));
	}
	return 0;
}

可持续化并查集

板子题:https://www.luogu.org/problem/P3402
参考代码:https://blog.csdn.net/chenxiaoran666/article/details/81505870

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;

int n,q,a[maxn],rt[maxn],cnt;
int fa[maxn*20],ls[maxn*20],rs[maxn*20];
int sz[maxn*20];

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void build(int &now,int l,int r)
{
	now=++cnt;
	int mid=(l+r)>>1;
	if(l==r){
		fa[now]=l;return;
	}
	build(ls[now],l,mid);build(rs[now],mid+1,r) ;
}
void update(int &now,int old,int l,int r,int x,int p)
{
	now=++cnt;
	if(l==r){
		fa[now]=p;sz[now]=sz[old];return;
	}
	int mid=(l+r)>>1;
	ls[now]=ls[old];rs[now]=rs[old];
	if(x<=mid) update(ls[now],ls[old],l,mid,x,p);
	else update(rs[now],rs[old],mid+1,r,x,p);
}
void Add_sz(int now,int l,int r,int x)
{
	if(l==r){
		++sz[now];return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) Add_sz(ls[now],l,mid,x);
	else Add_sz(rs[now],mid+1,r,x);
}
int query(int now,int l,int r,int x)
{
	if(l==r) return now;
	int mid=(l+r)>>1;
	if(x<=mid) return query(ls[now],l,mid,x);
	else return query(rs[now],mid+1,r,x);
}
int find1(int now,int x)
{
	int p=query(now,1,n,x);
	return fa[p]==x?p:find1(now,fa[p]);
}
void connect(int v,int x,int y)
{
	int fx=find1(rt[v],x),fy=find1(rt[v],y);
	if(fx==fy) return;
	if(sz[fx]<sz[fy]) swap(fx,fy);
	update(rt[v],rt[v-1],1,n,fa[fy],fa[fx]);
	if(sz[fx]==sz[fy]) Add_sz(rt[v],1,n,fa[fx]);
}
int main()
{
	n=read();q=read();
	cnt=0;
	build(rt[0],1,n);
	for(int i=1;i<=q;++i){
		int op,x,y;
		op=read();x=read();
		if(op^2) y=read(),rt[i]=rt[i-1];
		switch(op){
			case 1:connect(i,x,y);break;
			case 2:rt[i]=rt[x];break;
			case 3:{
				if((find1(rt[i],x)==find1(rt[i],y))) puts("1");
				else puts("0");
				break;
			}
		}
	}
	return 0;
}

[SDOI2010]粟粟的书架

P2468
原题链接:https://www.luogu.org/problem/P2468
参考:https://www.cnblogs.com/neighthorn/p/6400438.html
题解:小数据部分用二维前缀和,大数据部分用裸的主席树。

#include<bits/stdc++.h>
using namespace std;
const int maxn=210;
const int maxm=1010;
const int N=500010;
const int M=7000010;

int n,m,q,p[maxn][maxn],f[maxn][maxn][maxm];
int g[maxn][maxn][maxm];
int cnt,G[N],ls[M],rs[M],sum[M],num[M],root[N];


void solve1()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&p[i][j]);
	memset(f,0,sizeof(f));
	memset(g,0,sizeof(g));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			for(int k=1;k<=1000;k++)
				f[i][j][k]=f[i][j-1][k]+f[i-1][j][k]-f[i-1][j-1][k],
				g[i][j][k]=g[i][j-1][k]+g[i-1][j][k]-g[i-1][j-1][k];
			f[i][j][p[i][j]]+=p[i][j],g[i][j][p[i][j]]++;
		}
	for(int k=999;k>=1;k--)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				f[i][j][k]+=f[i][j][k+1],g[i][j][k]+=g[i][j][k+1];
	for(int i=1,x1,y1,x2,y2,h;i<=q;i++){
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&h);
		int l=1,r=1000,ans=-1;
		while(l<=r){
            int mid=(l+r)>>1;
            if(f[x2][y2][mid]-f[x1-1][y2][mid]-f[x2][y1-1][mid]+f[x1-1][y1-1][mid]>=h)
                ans=mid,l=mid+1;
            else
                r=mid-1;
        }
        if(ans==-1)
            puts("Poor QLW");
		else{
			int cnt=g[x2][y2][ans]-g[x1-1][y2][ans]-g[x2][y1-1][ans]+g[x1-1][y1-1][ans];
			int tmp=(g[x2][y2][ans]-g[x2][y2][ans+1])-(g[x1-1][y2][ans]-g[x1-1][y2][ans+1])
				    -(g[x2][y1-1][ans]-g[x2][y1-1][ans+1])+(g[x1-1][y1-1][ans]-g[x1-1][y1-1][ans+1]);
			int num=f[x2][y2][ans]-f[x1-1][y2][ans]-f[x2][y1-1][ans]+f[x1-1][y1-1][ans];
			cnt-=tmp;
			while(tmp&&num-ans>=h) tmp--,num-=ans;
			printf("%d\n",cnt+tmp);
		}
	}
}
void update(int &now,int old,int l,int r,int pos)
{
	now=++cnt;
	sum[now]=sum[old]+pos;num[now]=num[old]+1;
	ls[now]=ls[old];rs[now]=rs[old];
	if(l==r) return;
	int mid=(l+r)>>1;
	if(pos<=mid) update(ls[now],ls[old],l,mid,pos);
	else update(rs[now],rs[old],mid+1,r,pos);
}
int query(int now,int old,int l,int r,int val)
{
	if(l==r) return (val-1)/l+1;
	int mid=(l+r)>>1;
	if(sum[rs[now]]-sum[rs[old]]>=val)
		return query(rs[now],rs[old],mid+1,r,val);
	else
		return query(ls[now],ls[old],l,mid,val-(sum[rs[now]]-sum[rs[old]]))+num[rs[now]]-num[rs[old]];
}
void solve2()
{
	n=m;cnt=0;
	memset(sum,0,sizeof(sum));
	memset(num,0,sizeof(num));
	for(int i=1,x;i<=n;i++)
		scanf("%d",&x),G[i]=G[i-1]+x,update(root[i],root[i-1],1,1000,x);
	for(int i=1,x1,y1,x2,y2,h;i<=q;i++){
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&h);
		if(G[y2]-G[y1-1]<h) puts("Poor QLW");
		else printf("%d\n",query(root[y2],root[y1-1],1,1000,h));
	}
} 
int main()
{
	scanf("%d%d%d",&n,&m,&q);
	if(n!=1) solve1();
	else solve2();
	return 0;
}

[CTSC2018]混合果汁

P4602
题目链接:https://www.luogu.org/problem/P4602
参考:https://www.cnblogs.com/HocRiser/p/9046588.html
题解:二分美味度,建多棵美味度线段树,以价格为权值。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=100010;
const int mx=100000;
const int maxm=1000010;

struct node{
	int d,p,l;
}a[maxn];
bool cmp(const node &x,const node &y)
{
	return x.d<y.d;
} 
int b[maxn];//美味度 
ll c[maxn];//c[i]表 美味度>=i 有多少升 
int n,m;
ll sum[maxn*20],sz[maxn*20];
int root[maxn*20],ls[maxn*20],rs[maxn*20];
int cnt;
void update(int &now,int old,int l,int r,int pos,int val)//以价格建权值树 
{
	now=++cnt;
	sum[now]=sum[old];sz[now]=sz[old];
	ls[now]=ls[old];rs[now]=rs[old];
	if(l==r){
		sum[now]+=1LL*l*val;sz[now]+=val;return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) update(ls[now],ls[old],l,mid,pos,val);
	else update(rs[now],rs[old],mid+1,r,pos,val);
	sum[now]=sum[ls[now]]+sum[rs[now]];
	sz[now]=sz[ls[now]]+sz[rs[now]];
}
ll query(int now,int l,int r,ll val)
{
	if(l==r) return 1LL*l*val;
	int mid=(l+r)>>1;
	if(sz[ls[now]]>=val) return query(ls[now],l,mid,val);
	else return sum[ls[now]]+query(rs[now],mid+1,r,val-sz[ls[now]]);
} 

ll g,h;
bool ok(int x)
{
	if(c[x]<h) return 0;
	ll tmp=query(root[x],1,mx,h);
	return tmp<=g;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].d,&a[i].p,&a[i].l);
	}
	sort(a+1,a+n+1,cmp);
	for(int i=mx,j=n;i>=1;i--){
		c[i]=c[i+1];
		while(j>=1&&a[j].d>=i) c[i]+=a[j].l,j--;
	}
	cnt=0;
	for(int i=mx,j=n;i>=1;i--){//美味度建线段树 
		root[i]=root[i+1];
		while(j>=1&&a[j].d>=i) update(root[i],root[i],1,mx,a[j].p,a[j].l),j--;
	}
	for(int i=1;i<=m;i++){
		scanf("%lld%lld",&g,&h);
		int l=1,r=mx;
		int ans=-1;
		while(l<=r){
			int mid=(l+r)>>1;
			if(ok(mid)){
				ans=mid;l=mid+1;
			}else{
				r=mid-1;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
} 

[2019寒假集训day3]欧铂瑞特
原题链接没找着
题解:https://blog.csdn.net/qq_34940287/article/details/87720345

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值