2019牛客国庆集训派对day3

链接:https://ac.nowcoder.com/acm/contest/1108/E
来源:牛客网

题意

在一个$10 ^ 9 * 10 ^ 9$ 的方格中,每次把$[l, r]$的每一行整行连通(行间没关系),或者把$[l, r]$列连通,输出连通块的个数,操作为$10 ^ 5$ 次。

思路

本题有个重要的特性,只要有一个行连通和列连通的操作后,之后的连通块就两种情况,一是各个单独成块的小格子,还有就是一个大连通块。

 我:先离散化,对行和列各搞了一个线段树,每次修改看影响了多少个单独的格子,在上次的答案中去掉即可,然后在线段树中标记去掉的列或行。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
//#include <unordered_set>
//#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 1e5+9;

            struct Q{
                int tp;
                int a, b;
            } qu[maxn];

            struct Tree{
                vector<int>vec;
                int getid(int x) {
                    return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
                }
                int N;
                void init(int n) {
                    vec.pb(1);
                    vec.pb(n+1);
                    sort(vec.begin(), vec.end());
                    vec.erase(unique(vec.begin(), vec.end()), vec.end());
                    N = vec.size() ;
                }
                ll sum[maxn << 2];
                ll lazy[maxn << 2];
                void build(int le, int ri, int rt, int val) {
                    lazy[rt] = -1;
                    if(le == ri) {
                        if(le < vec.size()) {
                            sum[rt] = 1ll * (vec[le] - vec[le-1] ) * val;
                        }
                        else sum[rt] = 0;
                        return;
                    }
                    int mid = (le + ri) >> 1;
                    build(le, mid, rt<<1, val);
                    build(mid+1, ri, rt<<1|1, val);
                    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
                }
                void pushdown(int le, int ri, int rt) {
                    lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
                    sum[rt<<1] = sum[rt<<1|1] = 0;
                    lazy[rt] = -1;
                }
                void update(int L, int R, int val, int le, int ri, int rt) {
                    if(le >= L && ri <= R) {
                        lazy[rt] = val;
                        sum[rt] = 0;
                        return;
                    }
                    if(lazy[rt] != -1) pushdown(le, ri, rt);
                    int mid = (le + ri) >> 1;
                    if(mid >= L) update(L, R, val, le, mid, rt<<1);
                    if(mid < R) update(L, R, val, mid+1, ri, rt<<1|1);
                    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
                }
                int query(int L, int R, int le, int ri, int rt) {
                    if(le >= L && ri <= R) {
                        return sum[rt];
                    }
                    if(lazy[rt] != -1) pushdown(le, ri, rt);
                    int mid = (le + ri) >> 1;
                    int res = 0;
                    if(mid >= L) res += query(L, R, le, mid, rt<<1);
                    if(mid < R) res += query(L ,R, mid+1, ri, rt<<1|1);
                    return res;
                }
            } tr[2];
int main(){
            int n,m,q;
            while(~scanf("%d%d%d", &n, &m, &q)) {
                tr[0].vec.clear();
                tr[1].vec.clear();
                for(int i=1; i<=q; i++) {
                    scanf("%d%d%d", &qu[i].tp, &qu[i].a, &qu[i].b);
                    qu[i].tp --;
                    tr[qu[i].tp].vec.pb(qu[i].a);
                    tr[qu[i].tp].vec.pb(qu[i].b+1);
                }
                tr[0].init(n);
                tr[1].init(m);

                tr[0].build(1, tr[0].N, 1, 1);
                tr[1].build(1, tr[1].N, 1, 1);


                int pretp = -1, flag = 1;
                int wai = 0;
                ll ans = 1ll*n * m;


                for(int i=1; i<=q; i++) {
                    int tp = qu[i].tp, a = qu[i].a, b = qu[i].b;
                    if(pretp != -1 && flag && pretp != tp) {
                        wai = 1;
                        flag = 0;
                    }
                    if(tp == 0) {
                        ll k = tr[1].sum[1];
                        ans -= 1ll*(tr[0].query(tr[0].getid(qu[i].a), tr[0].getid(qu[i].b + 1) - 1, 1, tr[0].N, 1)) * k;
                        if(flag) wai += tr[0].query(tr[0].getid(qu[i].a), tr[0].getid(qu[i].b + 1) - 1, 1, tr[0].N, 1);
                        tr[0].update(tr[0].getid(qu[i].a), tr[0].getid(qu[i].b + 1) - 1, 0, 1, tr[0].N, 1);
                    }
                    else {
                        ll k = tr[0].sum[1];
                        ans -= 1ll*(tr[1].query(tr[1].getid(qu[i].a), tr[1].getid(qu[i].b + 1) - 1, 1, tr[1].N, 1)) * k;
                        if(flag) wai += tr[1].query(tr[1].getid(qu[i].a), tr[1].getid(qu[i].b + 1) - 1, 1, tr[1].N, 1);
                        tr[1].update(tr[1].getid(qu[i].a), tr[1].getid(qu[i].b + 1) - 1, 0, 1, tr[1].N, 1);
                    }
                    pretp = tp;
                    printf("%lld\n", ans + wai);
                }
            }
            return 0;
}
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-01
  • 2021-09-06
  • 2021-07-02
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-09-16
  • 2021-04-26
  • 2020-01-01
  • 2021-08-21
  • 2023-01-07
  • 2022-12-23
相关资源
相似解决方案