• 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]);
    }
    
  • 相关阅读:
    拖拽系列二、利用JS面向对象OOP思想实现拖拽封装
    拖拽系列一、JavaScript实现简单的拖拽效果
    CSS3中三角形及三角形组合图实现
    计算机内存管理介绍
    [Leetcode]双项队列解决滑动窗口最大值难题
    [Leetcode]827.使用回溯+标记解决最大人工岛问题
    计算机启动过程
    [Leetcode]895.最大频率栈
    GDB查看内存(x 命令)
    理解递归
  • 原文地址:https://www.cnblogs.com/lcxer/p/10268639.html
Copyright © 2020-2023  润新知