bzoj3022[Balkan2012]The Best Teams

传送门


上面是题目意思哦!

(友情提供一组样例)

sample input

7
17 21
24 36
14 19
27 20
21 50
18 5
33 7
4
20 3
50 2
99 5
10 2

output

45
71
95
0
这个题首先将水平排序,然后按照水平建线段树。(只是建颗线段树吧)
然后再将球员和询问按年龄排序一下,这样就只需要考虑水平问题了
由于我们是按水平建的线段树,所以从右往左查k个不连续的值就行了
考虑线段树上每个节点保存这几个信息:
(g[0/1]:r+1)不选/选的时候,(l)选不选,
(c[0/1]:r+1)不选/选的时候,区间内选了几个,
(s[0/1]:r+1)不选/选的时候,区间内选数的和。
然后查询的时候肯定最先选最大的(也就是初始情况为什么r+1不选),具体原因可以自己思考

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
	char ch; bool ok;
	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=3e5+1;
int n,m,id[maxn];long long ans[maxn];
struct oo{int x,y,z;}a[maxn],b[maxn];
struct segment_tree{int l,r,c[2];bool g[2];long long s[2];}s[maxn*4];
bool cmp(oo a,oo b){return a.y<b.y;}
bool cmp1(oo a,oo b){return a.x<b.x;}
void build(int x,int l,int r)
{
	s[x].l=l,s[x].r=r;
	if(l==r)return ;int mid=(l+r)>>1;
	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
}
void update(int x)
{
	s[x].g[0]=s[x<<1].g[s[x<<1|1].g[0]],s[x].g[1]=s[x<<1].g[s[x<<1|1].g[1]];
	s[x].c[0]=s[x<<1].c[s[x<<1|1].g[0]]+s[x<<1|1].c[0];
	s[x].c[1]=s[x<<1].c[s[x<<1|1].g[1]]+s[x<<1|1].c[1];
	s[x].s[0]=s[x<<1].s[s[x<<1|1].g[0]]+s[x<<1|1].s[0];
	s[x].s[1]=s[x<<1].s[s[x<<1|1].g[1]]+s[x<<1|1].s[1];
}
void change(int x,int l,int v)
{
	if(s[x].l==s[x].r){s[x].g[0]=1,s[x].c[0]=1,s[x].s[0]=v;return ;}
	int mid=(s[x].l+s[x].r)>>1;
	if(l<=mid)change(x<<1,l,v);else change(x<<1|1,l,v);
	update(x);
}
long long get(int x,int k,bool id)
{
	if(s[x].l==s[x].r)return s[x].s[id];
	if(k<=s[x<<1|1].c[id])return get(x<<1|1,k,id);
	else return s[x<<1|1].s[id]+get(x<<1,k-s[x<<1|1].c[id],s[x<<1|1].g[id]);
}
int main()
{
	read(n);
	for(rg int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].z=i;
	read(m);
	for(rg int i=1;i<=m;i++)scanf("%d%d",&b[i].x,&b[i].y),b[i].z=i;
	sort(a+1,a+n+1,cmp);for(rg int i=1;i<=n;i++)id[a[i].z]=i;
	sort(a+1,a+n+1,cmp1),sort(b+1,b+m+1,cmp1);int now=1;build(1,1,n);
	for(rg int i=1;i<=m;i++)
	{
		while(a[now].x<=b[i].x&&now<=n)change(1,id[a[now].z],a[now].y),now++;
		ans[b[i].z]=get(1,b[i].y,0);
	}
	for(rg int i=1;i<=m;i++)printf("%lld
",ans[i]);
}
原文地址:https://www.cnblogs.com/lcxer/p/10268639.html