bzoj2811 [Apio2012]Guard

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2811

【题解】

首先我们先把没看到忍者的段去掉,可以用线段树做。

如果剩下的就是K,那么特判即可。

我们可以把包含关系去掉然后对于剩下的区间,x单增,y单增。

否则的话,我们有一个结论(挺显然的):只有每个区间的右段点才能成为答案。

我们贪心地填肯定是填右端点。

所以我们判断如果右端点填到了前一个位置是否可行即可,如果不可行那么必须填右端点。

二分出这个位置所覆盖的区间(我们钦定填了这里)

然后我们维护fp[i]表示左边i个区间最少填多少,fs[i]表示右边i个区间最少填多少(前缀、后缀)

然后我们判断fp[l]+fs[r]+1是否大于K即可,如果大于,说明一定要填。

# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, K, m;

int x[M];
struct guard {
    int l, r;
    guard() {}
    guard(int l, int r) : l(l), r(r) {}
    friend bool operator < (guard a, guard b) {
        return a.l < b.l || (a.l == b.l && a.r > b.r);
    }
}a[M], o[M]; int on;

bool del[M];
int new_id[M], idx, old_id[M];
int pre[M], nxt[M];
int fp[M], fs[M];

namespace SMT {
    int w[M];
    # define ls (x<<1)
    # define rs (x<<1|1)
    inline void edt(int x, int l, int r, int L, int R) {
         if(w[x]) return;
        if(L <= l && r <= R) {
            w[x] = 1;
            return ;
        }
        int mid = l+r>>1;
        if(L <= mid) edt(ls, l, mid, L, R);
        if(R > mid) edt(rs, mid+1, r, L, R);
    }
    inline int query(int x, int l, int r, int pos) {
        if(w[x]) return 1;
        if(l == r) return 0;
        int mid = l+r>>1;
        if(pos <= mid) return query(ls, l, mid, pos);
        else return query(rs, mid+1, r, pos);
    }
    # undef ls
    # undef rs
}

int main() {
    scanf("%d%d%d", &n, &K, &m);
    for (int i=1; i<=m; ++i) scanf("%d%d%d", &a[i].l, &a[i].r, x+i);
    for (int i=1; i<=m; ++i) if(x[i] == 0) SMT::edt(1, 1, n, a[i].l, a[i].r);
    for (int i=1; i<=n; ++i) {
        if(SMT::query(1, 1, n, i) == 0) {
            new_id[i] = ++idx, old_id[idx] = i;
//            printf("i = %d, idx = %d\n", i, idx);
        }
        else del[i] = 1;
    }
    if(idx == K) {
        for (int i=1; i<=n; ++i)
            if(!del[i]) printf("%d\n", i);
        return 0;
    }
    for (int i=1; i<=n; ++i) {
        if(!del[i]) pre[i] = i;
        else pre[i] = pre[i-1];
    }
    for (int i=n; i; --i) {
        if(!del[i]) nxt[i] = i;
        else nxt[i] = nxt[i+1];
    }
    for (int i=1; i<=m; ++i) {
        int nl = nxt[a[i].l], nr = pre[a[i].r];
        if(nl <= nr) o[++on] = guard(new_id[nl], new_id[nr]);
    }
    sort(o+1, o+on+1);
    m = 0;
    for (int i=1; i<=on; ++i) {
        while(m && o[i].l >= a[m].l && o[i].r <= a[m].r) --m;
        a[++m] = o[i];
    }
//    for (int i=1; i<=m; ++i)
//        printf("%d %d\n", a[i].l, a[i].r);
    int cur = 0;
    for (int i=1; i<=m; ++i)
        if(a[i].l > cur) fp[i] = fp[i-1] + 1, cur = a[i].r;
        else fp[i] = fp[i-1];
    cur = 1e9;
    for (int i=m; i; --i)
        if(a[i].r < cur) fs[i] = fs[i+1] + 1, cur = a[i].l;
        else fs[i] = fs[i+1];

    bool have_ans = 0; 

    for (int i=1, x, l, r, ans1, ans2; i<=m; ++i) {
        if(fp[i] != fp[i-1]+1) continue;
        if(a[i].l == a[i].r) {
            have_ans = 1;
//            printf("=%d\n", a[i].r);
            printf("%d\n", old_id[a[i].r]);
            continue;
        }
        // 考察每个区间的右端点是否可行
        x = a[i].r-1;
        l = 1, r = i-1, ans1 = 0;
        while(1) {
            if(r-l<=3) {
                for (int j=r; j>=l; --j)
                    if(a[j].r < x) {
                        ans1 = j;
                        break;
                    }
                break;
            }
            int mid = l+r>>1;
            if(a[mid].r < x) l = mid;
            else r = mid;
        }
        l = i+1, r = m, ans2 = m+1;
        while(1) {
            if(r-l<=3) {
                for (int j=l; j<=r; ++j)
                    if(a[j].l > x) {
                        ans2 = j;
                        break;
                    }
                break;
            }
            int mid = l+r>>1;
            if(a[mid].l > x) r = mid;
            else l = mid;
        }
//        printf("%d %d\n", ans1, ans2);
        if(fp[ans1] + fs[ans2] + 1 > K) {
//            printf("=%d\n", a[i].r);
            printf("%d\n", old_id[a[i].r]);
            have_ans = 1;
        }
    }

    if(!have_ans) puts("-1");

    return 0;
}

时间: 2024-08-05 03:00:09

bzoj2811 [Apio2012]Guard的相关文章

Data guard概念篇一(转载)

本文转载至以下链接,感谢作者分享! http://tech.it168.com/db/2008-02-14/200802141545840_1.shtml 一.Data Guard配置(Data Guard Configurations) Data Guard是一个集合,由一个primary数据库(生产数据库)及一个或多个standby数据库(最多9个)组成.组成Data Guard的数据库通过Oracle Net连接,并且有可能分布于不同地域.只要各库之间可以相互通信,它们的物理位置并没有什么

portfast与bpdu guard

BPDU guard的功能是当这个端口收到任何的BPDU 就马上设为Error-Disabled状态.我们知道,当交换机STP功能启用的时候,默认所有端口都会参与STP,并发送和接受BPDU . 当BPDU guard开启后,在正常情况下,一个下联寝室的端口是不会收到任何BPDU的,因为PC和小交换机都不支持STP,所以不会收发BPDU. 当这个端口下如果有自回环的环路,那么它发出去的BPDU在小交换机上回环后就会被自己接收到,这个时候BPDUguard就会把它立刻设为Error-Disable

YH1:Oracle Data Guard知识库

小编:大家对Oracle DataGuard 应该很熟吧? 众人:那是相当熟. 小编:好的,那我们今天就不讲基础知识了,直入主题!跟不上课的孩子自己回去补. 今天的话题包括: 12.2中ADG的性能与诊断 ADG上部署列式存储 DG跨平台迁移 DG数据恢复 DG的归档管理 12.2中ADG的性能与诊断 在Oracle 12.2中,ADG有许多惊人的改进,通过ADG standby数据库的性能数据收集和诊断.快照standby数据库的应用,以及实时的数据库操作监控的实现,能够根据用户需求相协调来提

洛谷P3112 [USACO14DEC]后卫马克Guard Mark

题目描述 Farmer John and his herd are playing frisbee. Bessie throws the frisbee down the field, but it's going straight to Mark the field hand on the other team! Mark has height H (1 <= H <= 1,000,000,000), but there are N cows on Bessie's team gathere

Hadoop 2.4 libhadoop.so的disabled stack guard问题

由于2.4.0默认配置的libhadoop是32位的,在64位的操作系统环境运行过程中,会提示以下错误: Java HotSpot(TM) 64-Bit Server VM warning: You have loaded library /opt/hadoop-2.2.0/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard. The VM will try to fix the stack guard now.

Data guard概念篇二(转载)

本文转载至以下链接,感谢作者分享! http://tech.it168.com/db/2008-02-14/200802141545840_1.shtml 一.Standby数据库类型     前章我们简单介绍了Standby数据库,并且也知道其通常分为两类:物理standby和逻辑standby,同时也简短的描述了其各自的特点,下面我们就相关方面进行一些稍深入的研究: 1. 物理standby 我们知道物理standby与primary数据库完全一模一样(默认情况下,当然也可以不一样,事无绝对

Oracle RAC + Data Guard 环境搭建

国庆之前就准备做这个实验了. 后来时间不够,就没搞了. 6天的长假一放,都散漫的不成样子了.懒散了很多. 今天7号. 上班也没啥精神,但是该做的实验还得继续. Oracle 高可用性的三个主要体现是: RAC, Data Guard 和 Stream.  所以熟练掌握这些技术就是评价DBA的标准一个. RAC + Data Guard 主要用在灾备或者报表服务器上. 比如用RAC+ 逻辑standby 做报表,从而减轻RAC 系统的压力. 关于Data Guard 的一些原理知识可以参考: Or

bzoj2809[Apio2012]dispatching

bzoj2809[Apio2012]dispatching 题意: n个点组成一棵树,每个点都有一个领导力和费用,可以让一个点当领导,然后在这个点的子树中选择一些费用之和不超过m的点,得到领导的领导力乘选择的点的个数(领导可不被选择)的利润.求利润最大值.n≤100000 题解: 可并堆.可以得到一个结论,就是在子树中选点的时候,先选所有点,如果费用超了,就不断把费用最大的剔除,知道费用不超,这样得到的选点数量最大,这过程可以用堆维护.同时每个点的堆都可以由子树的堆合并得到,所以需要可并堆. 代

Data Guard - Snapshot Standby Database配置

转载自:https://blogs.oracle.com/Database4CN/entry/data_guard_snapshot_standby_database 概述 一般情况下,物理standby数据库处于mount状态接收和应用主库的REDO日志,物理standby数据库不能对外提供访问.如果需要只读访问,那么可以临时以read-only的方式open物理备库,或者配置ACTIVE DATA GUARD,那么物理standby数据库可以进行只读(read-only)访问(比如报表业务查