CodeForces 12D Ball 多级排序 + 离散 + 线段树

给出B,I,R,对于Pi,若存在Pj满足 Bi < Bj && Ii < Ij && Ri < Rj ,则称Pi为 probable self-murderers。问存在多少个Pi。

首先对其升序排序,优先级为B > I > R。

然后发现对于i < j ,必有Bi <= Bj,所以这一层基本可以忽略。

然后由于数据范围较大,对 I 进行离散,建立线段树记录大于I的区间内最大的R是多少,当然此时要从后往前扫描,边更新边计数。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007

using namespace std;

struct N
{
    int b,s,r;
} sta[500010];

bool cmp(N n1,N n2)
{
    if(n1.b != n2.b)
        return n1.b < n2.b;
    if(n1.s != n2.s)
        return n1.s < n2.s;
    return n1.r < n2.r;
}

int num[500010];

int DelSame(int *num,int Top)
{
    int i,j;

    for(i = 2,j = 1; i <= Top; ++i)
        if(num[i] != num[j])
            num[++j] = num[i];
    return j;
}

int BS(int *num,int l,int r,int x)
{
    int mid;

    while(l <= r)
    {
        mid = (l+r)>>1;

        if(num[mid] == x)
            return mid;
        if(num[mid] < x)
            l = mid+1;
        else
            r = mid-1;
    }
    return -1;
}

int st[2000010];

int Updata(int site,int l,int r,int x,int d)
{
    if(l == r && r == x)
        return st[site] = max(st[site],d);

    int mid = (l+r)>>1;

    if(x <= mid)
        return st[site] = max(st[site],Updata(site<<1,l,mid,x,d));
    return st[site] = max(st[site],Updata(site<<1|1,mid+1,r,x,d));
}

int Query(int site,int L,int R,int l,int r)
{
    if(L == l && R == r)
        return st[site];
    int mid = (L+R)>>1;

    if(r <= mid)
        return Query(site<<1,L,mid,l,r);
    if(mid < l)
        return Query(site<<1|1,mid+1,R,l,r);
    return max(  Query(site<<1,L,mid,l,mid), Query(site<<1|1,mid+1,R,mid+1,r) );
}

int main()
{
    int n,i,j;

    scanf("%d",&n);

    for(i = 0; i < n; ++i)
        scanf("%d",&sta[i].b);
    for(i = 0; i < n; ++i)
        scanf("%d",&sta[i].r);
    for(i = 0; i < n; ++i)
        scanf("%d",&sta[i].s);

    sort(sta,sta+n,cmp);

    int Top = 0;

    for(i = 0; i < n; ++i)
        num[++Top] = sta[i].r;

    sort(num+1,num+Top+1);

    Top = DelSame(num,Top);

//    for(i = 1;i <= Top; ++i)
//        printf("%d %d\n",i,num[i]);

//    for(i = 0; i < n; ++i)
//        printf("i = %d %d %d %d\n",i,sta[i].b,sta[i].r,sta[i].s);

    memset(st,0,sizeof(st));

    int site,ans = 0,tmp;

    int R = n-1,val = sta[n-1].b;

    for(i = n-1; i >= 0; --i)
    {
        if(sta[i].b == val)
            continue;

        for(j = i+1; j <= R; ++j)
        {
            site = BS(num,1,Top,sta[j].r);
            if(site != Top && (tmp = Query(1,1,Top,site+1,Top)) > sta[j].s)
               ans++;
        }
        for(j = i+1; j <= R; ++j)
        {
            site = BS(num,1,Top,sta[j].r);
            Updata(1,1,Top,site,sta[j].s);
        }
        R = i;
        val = sta[i].b;
    }
    for(j = i+1; j <= R; ++j)
    {
        site = BS(num,1,Top,sta[j].r);
        if(site != Top && (tmp = Query(1,1,Top,site+1,Top)) > sta[j].s)
            ans++;
    }

    printf("%d\n",ans);

    return 0;
}
时间: 2024-10-14 15:16:22

CodeForces 12D Ball 多级排序 + 离散 + 线段树的相关文章

Codeforces 12D Ball 树状数组模拟3个元素的排序

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

codeforces 12D Ball

codeforces 12D Ball 这道题有两种做法 一种用树状数组/线段树维护区间最值,一种用map维护折线,昨天我刚遇见了一道类似的用STL维护折线的题目: 392D Three Arrays 参考题解:http://blog.csdn.net/rzo_kqp_orz/article/details/70666174 参考代码:http://codeforces.com/contest/392/submission/8930531 现在来谈谈这道题: (借一下另一题题解的图) 假设现在图

(中等) POJ 2528 Mayor&#39;s posters , 离散+线段树。

Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for

codeforces 444 C. DZY Loves Colors(线段树)

题目大意: 1 l r x操作 讲 [l,r]上的节点涂成x颜色,并且每个节点的值都加上 |y-x| y为涂之前的颜色 2 l r  操作,求出[l,r]上的和. 思路分析: 如果一个区间为相同的颜色.那么我们才可以合并操作. 所以我们之前找相同的区间就好. 但是问题是如何合并操作. 那么我们定义一个val  表示这个区间每个位置上应该加上的值. pushdown 的时候这个值是可以相加的. #include <cstdio> #include <iostream> #includ

POJ 2528 Mayor&#39;s posters(离散+线段树)

题目大意:往一面墙上贴与墙等高的海报,n次贴完后,求可以看见的海报总数(看见一部分也算) 思路:明显的区间维护,用线段树,不过裸的线段树超时超空间,可以把坐标离散,得到不超过200000个有效点,每个点都表示一个小区间(a[i]~a[i+1]这一段),然后就可以轻松地解决了.不过题目有个坑,给定的右坐标其实不是实际坐标,还要+1,区间总数等于有效点数 -1,更新的时候把查找到的右端点-1再代入,具体见代码: 1 /*****************************************

codeforces 446C DZY Loves Fibonacci Numbers 线段树

假如F[1] = a, F[2] = B, F[n] = F[n - 1] + F[n - 2]. 写成矩阵表示形式可以很快发现F[n] = f[n - 1] * b + f[n - 2] * a. f[n] 是斐波那契数列 也就是我们如果知道一段区间的前两个数增加了多少,可以很快计算出这段区间的第k个数增加了多少 通过简单的公式叠加也能求和 F[n]  = f[n - 1] * b + f[n - 2] * a F[n - 1] = f[n - 2] * b + f[n - 3] * a ..

Codeforces 444C DZY Loves Colors 水线段树

题目链接:点击打开链接 水.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set> #include <vector> #include <map> using namespace std; #define ll long long #defi

CodeForces - 383C Propagating tree(dfs + 线段树)

题目大意: 给出一棵树,树上每个节点都有权值,然后有两个操作. 1 x val 在结点x上加上一个值val,x的儿子加上 -val,x的儿子的儿子加上 - (-val),以此类推. 2 x 问x节点的值. 思路分析: 每个节点上加值都是给自己的儿子节点加,而且这个是颗树. 比如样例上的,如果你给node 1加一个值,那么五个节点都加. 再给node 2加个值,2的儿子节点也加了,之前给1加的值也要加到2号节点的儿子. 所以你会发现节点的儿子会存在一个从属的关系. 这样的话,我们可以把所有节点从新

codeforces Beta Round #19 D. Point (线段树 + set)

题目大意: 对平面上的点进行操作. add x y 在 (x,y )上加一个点. remove x y 移除 (x,y)上的点. find x y 求出在(x,y)右上角离他最近的点,优先级是靠左,靠下. 思路分析: find 操作 比较麻烦. 要保证x大的同时还要确保x最小,而且该x上还要有点. 这样要找大的时候要小的,就是在线段树上选择性的进入左子树还是右子树. 所以核心就是,用set维护叶子节点. 然后查找的时候去叶子节点找,如果这个叶子节点有蛮子的 x y  就输出,否则回溯去另外一个子