首页 > 其他分享 >[GYM103119K][2020 ICPC Asia Macau] Candy Ads 题解

[GYM103119K][2020 ICPC Asia Macau] Candy Ads 题解

时间:2024-09-25 21:39:09浏览次数:10  
标签:ok Ads Macau int 题解 DFS 广告 include bitset

题意简述

有 \(n\) 个广告,每个广告在一个时间段内占据二维平面的矩形,\(m\) 个约束表示两个广告至少有一个要被选择,选择若干广告,满足所有约束且同时刻不能有重叠的广告。

Kosaraju 算法流程

  1. 在正图上跑一遍 DFS,给每个位置打上时间戳
  2. 从时间戳大到小枚举点,在反图上跑 DFS,这个时候对于一个起点,他能搜到的所有点就和他在同一个强连通分量里。

思路

考虑 2-SAT,可以 \(O(n^2)\) 建边跑 Tarjan,算法瓶颈在于建边,注意到数据范围用 bitset 刚好可以,考虑用 bitset 维护偏序关系,具体而言预处理每一个偏序维度的前后缀 bitset,表示哪些广告满足这个不等式,然后对于一个广告,在三个维度上用前后缀 bitset 与出来所有和它有交的广告就行了。

这样实现了 \(O(\dfrac{n^2}{\omega})\) 建图,然而边数依旧是 \(O(n^2)\) 的,无论如何 Tarjan 都跑不动,考虑使用 Kosaraju 算法求 SCC。

这个算法的好处是只需要跑朴素的 DFS 就可以完成缩点,所以不断使用 _Find_first() 函数就可以找到一个点出发的所有未被访问节点,因为一个点只会被访问一次,所以总复杂度是 \(O(\dfrac{n^2}{\omega})\)。

码来

// Copyright © 2024 Moyou
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <bitset>
//#define int long long
using namespace std;
const int N = 50005, M = 4005;

int n, m, w, h, l[N], r[N], x[N], y[N], edn[N << 1], timestamp, id[N << 1];
bitset<N> g[N], pre1[M], pre2[M], pre3[M], suf1[M], suf2[M], suf3[M], ok[2];
vector<int> G[N]; 
bool check(int x) {return x > n ? ok[1].test(x - n) : ok[0].test(x);}
int idi(int x) {return x > n ? x - n : x + n;}
void kosaraju1(int u) {
    ok[u > n].reset(u > n ? u - n : u);
    if(u <= n) {
        g[u] &= ok[1];
        for(int v = g[u]._Find_first(); g[u].any(); v = g[u]._Find_first()) {
            kosaraju1(v + n);
            g[u] &= ok[1];
        }
    }
    else {
        for(auto v : G[u - n])
            if(check(v)) 
                kosaraju1(v);
    }
    edn[++ timestamp] = u;
}
void kosaraju2(int u) {
    id[u] = timestamp;
    ok[u > n].reset(u > n ? u - n : u);
    if(u <= n) {
        for(auto v : G[u])
            if(check(v + n)) 
                kosaraju2(v + n);
    }
    else {
        g[u - n] &= ok[0];
        for(int v = g[u - n]._Find_first(); g[u - n].any(); v = g[u - n]._Find_first()) {
            kosaraju2(v);
            g[u - n] &= ok[0];
        }
    }
}
inline char get_char() {
    static char buf[1 << 16], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 16, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
    int x = 0, f = 1;
    char ch = get_char();
    while (!isalnum(ch)) (ch == '-' ? f = -1 : 1), ch = get_char();
    while (isalnum(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = get_char();
    return x * f;
}
void write(int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x >= 10) write(x / 10);
    putchar(x % 10 + '0');
    return;
}
signed main() {
    n = read(), w = read(), h = read();
    for(int i = 1; i <= n; i ++) {
        l[i] = read(), r[i] = read(), x[i] = read(), y[i] = read();
        pre1[l[i]].set(i), suf1[r[i]].set(i), pre2[x[i]].set(i), suf2[x[i] + w - 1].set(i), pre3[y[i]].set(i), suf3[y[i] + h - 1].set(i);
    }
    for(int i = 1; i < M; i ++)    pre1[i] |= pre1[i - 1], pre2[i] |= pre2[i - 1], pre3[i] |= pre3[i - 1];
    for(int i = M - 2; i; i --) suf1[i] |= suf1[i + 1], suf2[i] |= suf2[i + 1], suf3[i] |= suf3[i + 1];
    for(int i = 1; i <= n; i ++)
        g[i] = suf1[l[i]] & pre1[r[i]] & suf2[x[i]] & pre2[x[i] + w - 1] & suf3[y[i]] & pre3[y[i] + h - 1], g[i].reset(i);
    m = read();
    for(int i = 1, a, b; i <= m; i ++)
        a = read(), b = read(), G[a].push_back(b), G[b].push_back(a);
    ok[0].set(), ok[1].set();
    for(int i = 1; i <= n * 2; i ++) if(check(i)) kosaraju1(i);
    timestamp = 0;
    ok[0].set(), ok[1].set();
    for(int i = 1; i <= n; i ++)
        g[i] = suf1[l[i]] & pre1[r[i]] & suf2[x[i]] & pre2[x[i] + w - 1] & suf3[y[i]] & pre3[y[i] + h - 1], g[i].reset(i);
    for(int i = n * 2; i; i --) if(check(edn[i])) timestamp ++, kosaraju2(edn[i]);
    for(int i = 1; i <= n; i ++) if(id[i] == id[i + n]) return puts("No"), 0;
    puts("Yes"); 
    for(int i = 1; i <= n; i ++) {
        if(id[i] < id[n + i]) putchar('0');
        else putchar('1');
    }

    return 0;
}

标签:ok,Ads,Macau,int,题解,DFS,广告,include,bitset
From: https://www.cnblogs.com/MoyouSayuki/p/18432257

相关文章

  • 题解 洛谷P3398 仓鼠找 sugar
    原题链接:P3398仓鼠找sugar题解里大部分都是用的lca,然而我看不懂那些关于lca的性质是怎么证明出来的。不过这题可以直接用树链剖分来写,把模板套上去就好了。题意为查找两条路径是否存在公共点,我们只需要把其中一条路径上的点都赋值为1,然后查询另一条路径上的点的总和,如果总和......
  • [ARC062F] AtCoDeerくんとグラフ色塗り 题解
    思路对于一个点双,我们可以发现:假如它是一个简单环,那么它只能旋转这一个环,我们可以使用polya定理计算。假如它是多个环的组成,那么它的颜色可以随意调动,任何的情况都可以得到,那么假如说有\(m\)条边,方案数则为\(\binom{m+k-1}{k-1}\),我们只考虑每一种颜色的出现次数。对于......
  • 题解 QOJ5034【>.<】/ BC2401D【可爱路径】
    必可赛前公益众筹赛第一试Dhttps://qoj.ac/problem/5034,2022-2023集训队互测Round6(Nov12,2022)题目描述这原本是一道简单的最短路问题,但是由于种种地域文化,宗教信仰以及政治因素,原来一些或许可以行走的路径不能通行了。我们定义禁止路径为连续的经过一些特定的点的......
  • Luogu_P10977(AcWing_299) Cut the Sequence 题解
    解题思路考虑线性dp。首先如果存在\(a_i>m\),那肯定不满足条件,输出\(-1\)。设\(f_i\)表示前\(i\)个数分成若干段,然后每段最大数之和,其中每段内的整数之和不超过\(m\)。\(f_i\)肯定是由\(f_j\)(\(1\lej<i\))转移过来的,也就是前\(j\)个数分好后再加上\((j,i]\)这一......
  • 【OJ题解-1】稀疏矩阵乘法
    一、试题题面计算两个稀疏矩阵相乘,输出相乘的结果【输入输出约定】输入:第一行输入三个正整数p、q、r,表示p×q和q×r的两个矩阵相乘;(约定0<p,q,r≤1000)然后是第一个矩阵的输入,首先是一个整数m,表示矩阵一有m个非零元素;然后是m行,每行三个整数i,j,d,表示第i行,第j列的元素为d(约定......
  • P8906 [USACO22DEC] Breakdown P 题解
    P8906[USACO22DEC]BreakdownP题解显然的套路是删边转化为加边。考虑到维护整条路径不好维护,于是考虑转化维护\(f_{i,k},g_{i,k}\)分别表示\(1,n\)到\(i\)走了\(k\)步时的最短路。那么此时\(k\le4\)。我们先考虑\(f\)的转移,\(g\)的转移是等价的。那么对于\((......
  • 题解:CF573D Bear and Cavalry
    因为这是远古题目,所以根据现在的评测机速度,用\(O(nq)\)的做法也是可以过的。也就是说,我们可以每次操作直接修改对应位置上的数字,然后设计一种\(O(n)\)的算法求解答案。这道题类似资源分配型动态规划,所以我们可以设\(dp_i\)表示分配前\(i\)个人的答案。直接写是不行的,我......
  • 题解:AT_abc204_e [ABC204E] Rush Hour 2
    变形的dijkstra。先思考什么情况下需要等待以及等待多长时间最优。我们把题目上的计算方法按照当前的时间\(t\)和通过所需的时间\(f(t)\)列个函数关系:\[f(t)=t+c+\lfloor\frac{d}{t+1}\rfloor\]然后用Desmos画个图可以得到图像(其实就是对勾函数):因为\(c,d\geq0\),所......
  • [湖北省选模拟 2023] 棋圣 / alphago 题解
    很牛的题目啊。-Alex_Wei发现这个操作比较复杂但限制较弱,考虑通过考察“不变的量”来刻画操作。容易发现若为二分图,则初始颜色不同的一定不能移动到一起。又因为在存在环的图上这个限制很弱/目前较难考虑,所以先考虑树的情况,发现答案存在可能取到的上界,令\(c_{i,j}\)为初......
  • CF1119H Triple 题解
    DescriptionSK酱送给你了一份生日礼物。礼物是\(n\)个三元组\((a_i,b_i,c_i)\)和四个正整数\(x,y,z,k\)。你利用这\(n\)个三元组填充了\(n\)个数组,其中第\(i\)个数组中有\(x\)个\(a_i\),\(y\)个\(b_i\),\(z\)个\(c_i\)(所以第\(i\)个数组长度为\((x+y+z)\)。......