• P5445 [APIO2019]路灯 [树套树,set]


    判断连通性,就像狼人那题,我们设 (x,y) 连通就变成 (x,y) 这个点上有值。

    我们设当前 (now) 时刻,一共有 (T) 时刻,假设最开始 (now=0) 的时候连通,如果你不去动他,他的贡献就是不变的,意思是如果你 (t=0) 的时候他们就连通,那么你只需要查询这个点的值,以及减掉 (T-now * (连通))

    如果他不连通了,那么显然我们可以一样做,把 (x,y) 这个点减掉 (now-T),这样就可以消除之后的贡献了。

    以及如何维护连通性,你只需要知道两个是否在一个集合就好,这个判断一下set所在的左端点就可以了。

    
    // clang-format off
    // powered by c++11
    // by Isaunoya
    #include<bits/stdc++.h>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define Rep(i,x,y) for(register int i=(x);i>=(y);--i)
    using namespace std;using db=double;using ll=long long;
    using uint=unsigned int;using ull=unsigned long long;
    using pii=pair<int,int>;
    #define Tp template
    #define fir first
    #define sec second
    Tp<class T>void cmax(T&x,const T&y){if(x<y)x=y;}Tp<class T>void cmin(T&x,const T&y){if(x>y)x=y;}
    #define all(v) v.begin(),v.end()
    #define sz(v) ((int)v.size())
    #define pb emplace_back
    Tp<class T>void sort(vector<T>&v){sort(all(v));}Tp<class T>void reverse(vector<T>&v){reverse(all(v));}
    Tp<class T>void unique(vector<T>&v){sort(all(v)),v.erase(unique(all(v)),v.end());}inline void reverse(string&s){reverse(s.begin(),s.end());}
    const int SZ=1<<23|233;
    struct FILEIN{char qwq[SZ],*S=qwq,*T=qwq,ch;
    #ifdef __WIN64
    #define GETC getchar
    #else
    inline char GETC(){return(S==T)&&(T=(S=qwq)+fread(qwq,1,SZ,stdin),S==T)?EOF:*S++;}
    #endif
    inline FILEIN&operator>>(char&c){while(isspace(c=GETC()));return*this;}inline FILEIN&operator>>(string&s){s.clear();while(isspace(ch=GETC()));if(!~ch)return*this;s=ch;while(!isspace(ch=GETC())&&~ch)s+=ch;return*this;}
    inline FILEIN&operator>>(char*str){char*cur=str;while(*cur)*cur++=0;cur=str;while(isspace(ch=GETC()));if(!~ch)return*this;*cur=ch;while(!isspace(ch=GETC())&&~ch)*++cur=ch;*++cur=0;return*this;}
    Tp<class T>inline void read(T&x){bool f=0;while((ch=GETC())<48&&~ch)f^=(ch==45);x=~ch?(ch^48):0;while((ch=GETC())>47)x=x*10+(ch^48);x=f?-x:x;}
    inline FILEIN&operator>>(int&x){return read(x),*this;}inline FILEIN&operator>>(ll&x){return read(x),*this;}inline FILEIN&operator>>(uint&x){return read(x),*this;}inline FILEIN&operator>>(ull&x){return read(x),*this;}
    inline FILEIN&operator>>(double&x){read(x);bool f=x<0;x=f?-x:x;if(ch^'.')return*this;double d=0.1;while((ch=GETC())>47)x+=d*(ch^48),d*=.1;return x=f?-x:x,*this;}
    }in;
    struct FILEOUT{const static int LIMIT=1<<22;char quq[SZ],ST[233];int sz,O,pw[233];
    FILEOUT(){set(7);rep(i,pw[0]=1,9)pw[i]=pw[i-1]*10;}~FILEOUT(){flush();}
    inline void flush(){fwrite(quq,1,O,stdout),fflush(stdout),O=0;}
    inline FILEOUT&operator<<(char c){return quq[O++]=c,*this;}inline FILEOUT&operator<<(string str){if(O>LIMIT)flush();for(char c:str)quq[O++]=c;return*this;}
    inline FILEOUT&operator<<(char*str){if(O>LIMIT)flush();char*cur=str;while(*cur)quq[O++]=(*cur++);return*this;}
    Tp<class T>void write(T x){if(O>LIMIT)flush();if(x<0){quq[O++]=45;x=-x;}do{ST[++sz]=x%10^48;x/=10;}while(x);while(sz)quq[O++]=ST[sz--];}
    inline FILEOUT&operator<<(int x){return write(x),*this;}inline FILEOUT&operator<<(ll x){return write(x),*this;}inline FILEOUT&operator<<(uint x){return write(x),*this;}inline FILEOUT&operator<<(ull x){return write(x),*this;}
    int len,lft,rig;void set(int l){len=l;}inline FILEOUT&operator<<(double x){bool f=x<0;x=f?-x:x,lft=x,rig=1.*(x-lft)*pw[len];return write(f?-lft:lft),quq[O++]='.',write(rig),*this;}
    }out;
    struct Math{
    vector<int>fac,inv;int mod;
    void set(int n,int Mod){fac.resize(n+1),inv.resize(n+1),mod=Mod;rep(i,fac[0]=1,n)fac[i]=fac[i-1]*i%mod;inv[n]=qpow(fac[n],mod-2);Rep(i,n-1,0)inv[i]=inv[i+1]*(i+1)%mod;}
    int qpow(int x,int y){int ans=1;for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;return ans;}int C(int n,int m){if(n<0||m<0||n<m)return 0;return fac[n]*inv[m]%mod*inv[n-m]%mod;}
    int gcd(int x,int y){return!y?x:gcd(y,x%y);}int lcm(int x,int y){return x*y/gcd(x,y);}
    }math;
    // clang-format on
    
    int n, q;
    const int maxn = 3e5 + 53;
    int a[maxn];
    
    struct SegMentTree {
      int rt[maxn], cnt;
      int ls[maxn << 6], rs[maxn << 6], val[maxn << 6];
    
      SegMentTree() { cnt = 0; }
      
      void upd(int &p, int l, int r, int x, int v) {
        if (!p) p = ++cnt;
        val[p] += v;
        if (l == r) return;
        int mid = l + r >> 1;
        if (x <= mid)
          upd(ls[p], l, mid, x, v);
        else
          upd(rs[p], mid + 1, r, x, v);
      }
    
      int qry(int p, int a, int b, int l, int r) {
        if (!p) return 0;
        if (a <= l && r <= b) return val[p];
        int mid = l + r >> 1, ans = 0;
        if (a <= mid) ans += qry(ls[p], a, b, l, mid);
        if (b > mid) ans += qry(rs[p], a, b, mid + 1, r);
        return ans;
      }
    
      int low(int x) { return x & -x; }
    
      void add(int x, int y, int w) {
        for (; x < maxn; x += low(x)) upd(rt[x], 1, n + 1, y, w);
      }
    
      void add(int x, int y, int x2, int y2, int w) {
        add(x, y, w);
    		add(x, y2 + 1, -w);
        add(x2 + 1, y, -w);
        add(x2 + 1, y2 + 1, w);
      }
    
      int qry(int x, int y) {
        int ans = 0;
        for (; x; x ^= low(x)) ans += qry(rt[x], 1, y, 1, n + 1);
        return ans;
      }
    } smt;
    
    struct node {
      int l, r;
      bool operator<(const node &other) const { return r < other.r; }
    };
    set<node> s;
    
    signed main() {
      // code begin.
      in >> n >> q;
      ++ n;
      rep(i, 1, n) s.insert({ i, i });
      rep(i, 1, n - 1) {
        char c;
        in >> c;
        a[i] = (c ^ 48);
        if (a[i]) {
          auto it = --s.upper_bound({ 0, i });
          int lef = (*it).l;
          s.erase(it), s.erase({ i + 1, i + 1 });
          s.insert({ lef, i + 1 });
        }
      }
      for (auto it = s.begin(); it != s.end(); ++it) smt.add((*it).l, (*it).l, (*it).r, (*it).r, q);
      rep(i, 1, q) {
        char S[11];
        in >> S;
        if (*S == 'q') {
          int a, b;
          in >> a >> b;
          int ans = smt.qry(a, b);
          int l1 = (*s.lower_bound({ 0, a })).l;
          int l2 = (*s.lower_bound({ 0, b })).l;
          out << (ans - (q - i) * (l1 == l2)) << '
    ';
        } else {
          int x;
          in >> x;
          if (a[x]) {
            auto it = s.lower_bound({ 0, x });
            int l1 = (*it).l, r1 = x;
            int l2 = x + 1, r2 = (*it).r;
            smt.add(l1, l2, r1, r2, i - q);
            s.erase({ l1, r2 });
            s.insert({ l1, r1 });
            s.insert({ l2, r2 });
            a[x] ^= 1;
          } else {
            auto it = s.lower_bound({ 0, x });
            int l1 = (*it).l, r1 = x;
            ++it;
            int l2 = x + 1, r2 = (*it).r;
            smt.add(l1, l2, r1, r2, q - i);
            s.erase({ l1, r1 });
            s.erase({ l2, r2 });
            s.insert({ l1, r2 });
            a[x] ^= 1;
          }
        }
      }
      return 0;
      // code end.
    }
    
  • 相关阅读:
    Typora 使用 Markdown 嵌入 LaTeX 数学公式符号语法
    爬虫常用的 urllib 库知识点
    执行Go程序的三种方式及Go语言关键字
    Win10 安装 MongoDB 3.6.5 失败的问题
    笨办法理解动态规划算法
    EclipseEE的Web开发环境配置(使用Tomcat作为Web服务器)
    二分类神经网络公式推导过程
    B+树在磁盘存储中的应用
    JAVA NIO工作原理及代码示例
    B树和B+树的插入、删除图文详解
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12580701.html
Copyright © 2020-2023  润新知