路灯「APIO 2019」

Posted ilverene

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了路灯「APIO 2019」相关的知识,希望对你有一定的参考价值。

题意

有、复杂,自己上网搜


思路

\((x,y)\) 表示从\(x\)\(y\)联通的时间长度。

那么查询操作相当于二维平面上的单点查询。

对于每一个\(i\),维护一个最左能到达的\(lm\),和最右能到达的\(rm\)

那么对于每一个更新操作,相当于对左上角为\((lm,i)\),右下角为\((i,rm)\)的矩形做修改。

于是就转换为类似「简单题」的题目了,可以CDQ分治解决,当然也可以直接上树套树。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO 
    
    template<typename T> inline void read (T &x) 
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    
    template<typename T> inline void write (T x) 
        if (x<0) putchar('-'),x=-x;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    
    


using namespace StandardIO;

namespace Solve 
    #define int long long
    
    const int N=300003;
    
    int n,q,sta,cnt;
    char s[N];
    int tree[N];
    struct node 
        int t,x,y,id;
        int type,val,ans;
        node () 
        node (int _t,int _x,int _y,int _ty,int _v,int _i) : t(_t),x(_x),y(_y),type(_ty),val(_v),id(_i) 
     w[N<<2],tmp[N<<2];
    int isQuery[N],ans[N];
    set<int> S;
    
    inline int pre (int x) 
        set<int>::iterator it=S.lower_bound(x);
        return *(--it);
    
    inline int suc (int x) 
        set<int>::iterator it=S.upper_bound(x);
        return *it;
    
    inline int lowbit (int x) 
        return x&(-x);
    
    inline void update (int x,int v) 
        for (register int i=x; i<=n; i+=lowbit(i)) 
            tree[i]+=v;
        
    
    inline int query (int x) 
        int res=0;
        for (register int i=x; i; i-=lowbit(i)) 
            res+=tree[i];
        
        return res;
    
    inline bool cmpt (const node &x,const node &y) 
        if (x.t!=y.t) return x.t<y.t;
        if (x.x!=y.x) return x.x<y.x;
        return x.y<y.y;
    
    inline bool cmpx (const node &x,const node &y) 
        if (x.x!=y.x) return x.x<y.x;
        return x.y<y.y;
    
    void merge (int l,int r) 
        int mid=(l+r)>>1;
        int ptr_l=l,ptr_r=mid+1,num=l-1;
        while (ptr_l<=mid&&ptr_r<=r) 
            if (cmpx(w[ptr_l],w[ptr_r])) tmp[++num]=w[ptr_l++];
            else tmp[++num]=w[ptr_r++];
        
        while (ptr_l<=mid) tmp[++num]=w[ptr_l++];
        while (ptr_r<=r) tmp[++num]=w[ptr_r++];
        for (register int i=l; i<=r; ++i) w[i]=tmp[i];
    
    void CDQ (int l,int r) 
        if (l==r) return;
        int mid=(l+r)>>1;
        CDQ(l,mid),CDQ(mid+1,r);
        int ptr=l-1;
        for (register int i=mid+1; i<=r; ++i) 
            while (ptr<mid&&w[ptr+1].x<=w[i].x) 
                ++ptr;
                if (w[ptr].type==1) update(w[ptr].y,w[ptr].val);
            
            if (w[i].type==2) w[i].ans+=query(w[i].y);
        
        for (register int i=l; i<=ptr; ++i) 
            if (w[i].type==1) update(w[i].y,-w[i].val);
        
        merge(l,r);
    
    inline void MAIN () 
        read(n),read(q);
        S.insert(0),S.insert(n+1);
        scanf("%s",s+1);
        for (register int i=1; i<=n; ++i) 
            if (s[i]=='0') 
                S.insert(i);
            
        
        for (register int i=1; i<=q; ++i) 
            string op;int x,y;
            cin>>op;
            if (op[0]=='t') 
                read(x),s[x]^=1;
                int l=pre(x)+1,r=suc(x)-1;
//              cout<<l<<' '<<r<<endl;
                if (s[x]=='0') 
                    w[++cnt]=node(i,l,x,1,i,19);
                    w[++cnt]=node(i,l,r+1,1,-i,260);
                    w[++cnt]=node(i,x+1,x,1,-i,8);
                    w[++cnt]=node(i,x+1,r+1,1,i,17);
                    S.insert(x);
                 else 
                    w[++cnt]=node(i,l,x,1,-i,19);
                    w[++cnt]=node(i,l,r+1,1,i,260);
                    w[++cnt]=node(i,x+1,x,1,i,8);
                    w[++cnt]=node(i,x+1,r+1,1,-i,17);
                    S.erase(x);
                
             else 
                read(x),read(y);
                isQuery[i]=1,++sta;
                // node (int _t,int _x,int _y,int _ty,int _v,int _i) : t(_t),x(_x),y(_y),type(_ty),val(_v),id(_i) 
                w[++cnt]=node(i,x,y-1,2,0,sta);
                if (suc(x)>y-1&&s[x]=='1'&&s[y-1]=='1') ans[sta]+=i;
            
        
        sort(w+1,w+cnt+1,cmpt);
//      for (register int i=1; i<=cnt; ++i) 
//          write(w[i].y),putchar('\n');
//      
        CDQ(1,cnt);
        for (register int i=1; i<=cnt; ++i) 
            if (w[i].type==2) 
                ans[w[i].id]+=w[i].ans;
            
        
        for (register int i=1; i<=sta; ++i) 
            write(ans[i]),putchar('\n');
        
    
    
    #undef int


int main () 
    Solve::MAIN();

以上是关于路灯「APIO 2019」的主要内容,如果未能解决你的问题,请参考以下文章

luoguP5445 [APIO2019]路灯 树套树+set

Luogu P5445 [APIO2019] 路灯

P5445 [APIO2019]路灯

「APIO2019」路灯 (K-D Tree / 树套树 / CDQ + 树状数组)

APIO2019 题解

#3144. 「APIO 2019」奇怪装置