zoukankan      html  css  js  c++  java
  • loj #3146. 「APIO 2019」路灯

    loj #3146. 「APIO 2019」路灯

    暴力的话就是查询((l,r))之间是否全部是1,考虑如何优化查询

    我们可以利用(set)来维护每一个全(1)区间和它出现的时间,具体的,用((lp,rp,l,r))来表示((lp,rp))的全(1)区间在时间([l,r])中是存在的

    那么对于一个在时间(i)的询问((l_i,r_i))((lp,rp,l,r))会对它产生贡献当且仅当(lpleq l_i,rpgeq r_i,igeq l),产生的贡献为(min(i,r)-l+1)

    注意到限制的条件其实是类似于三维偏序的,将全(1)区间的四元组也当做询问,我们按照(r)值降序所有的询问,进行(cdq)分治

    考虑前一半对后一半的贡献,两边分别按(l)升序排序,线段树维护这个类似区间长度的贡献即可

    细节稍微有点小多,而且由于过度使用stl所以常数巨大

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<math.h>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    const int N=10000;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define fir first
    #define sec second
    #define mp(a,b) make_pair(a,b)
    #define pb(a) push_back(a)
    #define maxd 998244353
    #define eps 1e-8
    struct segnode{
        int lp,rp,l,r;
    }seg[1200100];
    struct qnode{
        int l,r,tim,id;
    }q[300300];
    struct tnode{
        int op,id,r;
    }th[2002000];
    int ans[300300];
    int n,m,nowr[300300],id[300300],tot=0,sta[300300];
    int tr[2002000],add[2002000],qtot=0,tot1=0;
    set<int> nowl;
    set<int>::iterator iter;
    char s[300300],op[10];
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    void pushup(int id) {tr[id]=tr[id<<1]+tr[id<<1|1];}
    
    void pushdown(int id,int l,int r)
    {
        if (add[id])
        {
            int mid=(l+r)>>1;
            tr[id<<1]+=add[id]*(mid-l+1);
            tr[id<<1|1]+=add[id]*(r-mid);
            add[id<<1]+=add[id];add[id<<1|1]+=add[id];
            add[id]=0;
        }
    }
    
    void modify(int id,int l,int r,int ql,int qr,int val)
    {
        //cout << l << " " << r << " " << ql << " " << qr << " " << val << endl;
        if ((l>=ql) && (r<=qr))
        {
            tr[id]+=val*(r-l+1);
            add[id]+=val;return;
        }
        pushdown(id,l,r);
        int mid=(l+r)>>1;
        if (ql<=mid) modify(id<<1,l,mid,ql,qr,val);
        if (qr>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
        pushup(id);
    }
    
    int query(int id,int l,int r,int ql,int qr)
    {
        if ((l>=ql) && (r<=qr)) return tr[id];
        int mid=(l+r)>>1,ans=0;pushdown(id,l,r);
        if (ql<=mid) ans+=query(id<<1,l,mid,ql,qr);
        if (qr>mid) ans+=query(id<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    bool cmp1(tnode p,tnode q)
    {
        if (p.r!=q.r) return p.r>q.r;
        else return p.op<q.op;
    }
    
    bool cmp2(tnode x,tnode y)
    {
        if (x.op!=y.op) return x.op<y.op;
        else if (x.op==1) return seg[x.id].lp<seg[y.id].lp;
        else return q[x.id].l<q[y.id].l;
    }
    
    void solve(int l,int r)
    {
        if (l==r) return;
        int mid=(l+r)>>1;
        solve(l,mid);solve(mid+1,r);
        sort(th+l,th+mid+1,cmp2);
        sort(th+mid+1,th+r+1,cmp2);
        int p=l;
        rep(i,mid+1,r)
        {
            if (th[i].op==1) continue;
            while ((p<=mid) && (th[p].op==1) && (q[th[i].id].l>=seg[th[p].id].lp))
            {
                modify(1,1,m,seg[th[p].id].l,seg[th[p].id].r,1);
                p++;
            }
            ans[th[i].id]+=query(1,1,m,1,q[th[i].id].tim);
        }
        rep(i,l,p-1) modify(1,1,m,seg[th[i].id].l,seg[th[i].id].r,-1);
    }
    
    int main()
    {
        n=read();m=read();
        scanf("%s",s+1);
        rep(i,1,n) sta[i]=s[i]-'0';
        for (int i=1;i<=n;i++)
        {
            if (sta[i]==0) continue;
            int j=i;
            while ((j<=n) && (sta[j]==1)) j++;j--;
            nowr[i]=j;nowl.insert(i);
            id[i]=(++tot);
            seg[id[i]]=(segnode){i,j,1,m};i=j;
        }
        //for (iter=nowl.begin();iter!=nowl.end();iter++) cout << (*iter) << " ";cout << endl;
        //rep(i,1,n) cout << nowr[i] << " ";cout << endl;
        rep(i,1,m)
        {
            scanf("%s",op);
            if (op[0]=='t')
            {
                if (i==m) continue;
                int pos=read();sta[pos]^=1;
                if (sta[pos])
                {
                    int l=pos,r=pos;
                    iter=nowl.upper_bound(pos);
                    if (iter!=nowl.end())
                    {
                        int tmp=(*iter);
                        if (tmp==pos+1)
                        {
                            r=nowr[tmp];
                            seg[id[tmp]].r=i;nowl.erase(tmp);
                        }
                    }
                    iter=nowl.lower_bound(pos);
                    if (iter!=nowl.begin())
                    {
                        int tmp=*(--iter);
                        if (nowr[tmp]==pos-1)
                        {
                            l=tmp;
                            seg[id[tmp]].r=i;
                            nowl.erase(tmp);
                        }
                    }
                    id[l]=(++tot);nowr[l]=r;
                    seg[id[l]]=(segnode){l,r,i+1,m};
                    nowl.insert(l);
                }
                else
                {
                    iter=nowl.upper_bound(pos);iter--;
                    int l=(*iter),r=nowr[l];
                    seg[id[l]].r=i;
                    if (l<pos)
                    {
                        id[l]=(++tot);
                        seg[id[l]]=(segnode){l,pos-1,i+1,m};
                        nowr[l]=pos-1;
                    }
                    else nowl.erase(l);
                    if (r>pos)
                    {
                        id[pos+1]=(++tot);
                        seg[id[pos+1]]=(segnode){pos+1,r,i+1,m};
                        nowr[pos+1]=r;nowl.insert(pos+1);
                    }
                }
            }
            else
            {
                q[++qtot].id=qtot;q[qtot].tim=i;
                q[qtot].l=read();q[qtot].r=read()-1;
             }
        }
        //rep(i,1,qtot) cout << q[i].id << " " << q[i].l << " " << q[i].r << " " << q[i].tim << endl;
        rep(i,1,tot) th[++tot1]=(tnode){1,i,seg[i].rp};
        rep(i,1,qtot) th[++tot1]=(tnode){2,i,q[i].r};
        sort(th+1,th+1+tot1,cmp1);
        //rep(i,1,tot1) cout << th[i].id << " " << th[i].op << " " << th[i].r << endl;
        solve(1,tot1);
        rep(i,1,qtot) printf("%d
    ",ans[i]);
        return 0;
    }
            
    /*
    5 8
    11011
    query 1 2
    query 1 2
    query 1 6
    query 3 4
    toggle 3
    query 3 4
    toggle 2
    query 1 6
     */            
    
  • 相关阅读:
    JavaScript得到当前窗口的所有大小值
    JavaScript 变量、作用域和内存问题
    jQuery html5Validate基于HTML5表单验证插件
    新世界
    2001年的火花
    High Dynamic Range Compression on Programmable Graphics Hardware
    运筹帷幄
    你还要在学校找什么东西?
    图行天下
    Supra Team
  • 原文地址:https://www.cnblogs.com/encodetalker/p/11105339.html
Copyright © 2011-2022 走看看