zoukankan      html  css  js  c++  java
  • 洛谷P6783 [Ynoi2008] rrusq

    先将询问离线,从小到大扫描右端点并维护左端点的答案。让每个关键点在能覆盖它的矩形中编号最大一个有贡献,每次询问就是查询矩形对应的区间贡献和。

    每次右端点移动时,考虑新加入的矩形覆盖的点集,将该点集有贡献的位置修改为当前的右端点。这一过程可以用 (K-D Tree) 来维护,暴力回收子树内的标记,复杂度仍是正确的,因为回收标记时之前已经有打标记的复杂度了。

    一共有 (O(msqrt n)) 次单点修改和 (O(q)) 次区间查询,因此用分块来维护,总复杂度为 (Oleft(msqrt n+qsqrt m ight))

    #include<bits/stdc++.h>
    #define maxn 1000010
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,m,q,S,root,tot,type;
    int ans[maxn],bel[maxn],a[maxn],add[maxn];
    vector<pair<int,int> > ve[maxn];
    struct tree
    {
        int d[2],mx[2],mn[2],ls,rs,val,sum,tim,tag,vis;
    }t[maxn],dat[maxn];
    bool cmp(const tree &a,const tree &b)
    {
        return a.d[type]<b.d[type];
    }
    struct matrix
    {
        int u,d,l,r;
    }mt[maxn];
    void update(int x,int v)
    {
        a[x]+=v,add[bel[x]]+=v;
    }
    int ask(int x)
    {
        int v=0;
        for(int i=x;i<=min(S*bel[x],m);++i) v+=a[i];
        for(int i=bel[x]+1;i<=bel[m];++i) v+=add[i];
        return v;
    }
    void pushup(int x)
    {
        int ls=t[x].ls,rs=t[x].rs;
        for(int i=0;i<=1;++i)
        {
            t[x].mx[i]=t[x].mn[i]=t[x].d[i];
            if(ls)
            {
                t[x].mx[i]=max(t[x].mx[i],t[ls].mx[i]);
                t[x].mn[i]=min(t[x].mn[i],t[ls].mn[i]);
            }
            if(rs)
            {
                t[x].mx[i]=max(t[x].mx[i],t[rs].mx[i]);
                t[x].mn[i]=min(t[x].mn[i],t[rs].mn[i]);
            }
        }
        t[x].sum=t[ls].sum+t[rs].sum+t[x].val;
    }
    void del(int x)
    {
        if(t[x].tag) update(t[x].tag,-t[x].sum),t[x].tag=t[x].tim=0;
        if(t[x].tim) update(t[x].tim,-t[x].val),t[x].tim=0;
    }
    void pushdown(int x)
    {
        if(!t[x].tag) return;
        int ls=t[x].ls,rs=t[x].rs;
        del(ls),del(rs),t[ls].tag=t[ls].tim=t[rs].tag=t[rs].tim=t[x].tag;
        t[ls].vis=t[rs].vis=1,t[x].tag=0;
    }
    void build(int l,int r,int k,int &x)
    {
        x=++tot,type=k;
        int mid=(l+r)>>1;
        nth_element(dat+l+1,dat+mid+1,dat+r+1,cmp),t[x]=dat[mid];
        if(l<mid) build(l,mid-1,k^1,t[x].ls);
        if(r>mid) build(mid+1,r,k^1,t[x].rs);
        pushup(x);
    }
    bool check(int x,int p)
    {
        return mt[p].u<=t[x].d[0]&&mt[p].d>=t[x].d[0]&&mt[p].l<=t[x].d[1]&&mt[p].r>=t[x].d[1];
    }
    bool in(int x,int p)
    {
        return mt[p].u<=t[x].mn[0]&&mt[p].d>=t[x].mx[0]&&mt[p].l<=t[x].mn[1]&&mt[p].r>=t[x].mx[1];
    }
    bool out(int x,int p)
    {
        return mt[p].u>t[x].mx[0]||mt[p].d<t[x].mn[0]||mt[p].l>t[x].mx[1]||mt[p].r<t[x].mn[1];
    }
    void clear(int x)
    {
        if(!x||!t[x].vis) return;
        del(x),clear(t[x].ls),clear(t[x].rs),t[x].vis=0;
    }
    void modify(int x,int p)
    {
        if(!x||out(x,p)) return;
        if(in(x,p))
        {
            clear(x),update(t[x].tag=t[x].tim=p,t[x].sum),t[x].vis=1;
            return;
        }
        if(check(x,p)) update(t[x].tim,-t[x].val),update(t[x].tim=p,t[x].val);
        pushdown(x),t[x].vis=1,modify(t[x].ls,p),modify(t[x].rs,p);
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;++i)
            read(dat[i].d[1]),read(dat[i].val),dat[i].d[0]=i;
        read(m),S=sqrt(m);
        for(int i=1;i<=m;++i)
            bel[i]=(i-1)/S+1,read(mt[i].u),read(mt[i].d),read(mt[i].l),read(mt[i].r);
        read(q);
        for(int i=1,l,r;i<=q;++i)
            read(l),read(r),ve[r].push_back(make_pair(l,i));
        build(1,n,0,root);
        for(int i=1;i<=m;++i)
        {
            modify(root,i);
            for(int j=0;j<ve[i].size();++j)
                ans[ve[i][j].second]=ask(ve[i][j].first);
        }
        for(int i=1;i<=q;++i) printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    Scrapy的架构与原理的理解【转】
    Scrapy框架的命令行详解【转】
    WPF 程序中启动和关闭外部.exe程序
    C++ 二维数组(双重指针作为函数参数)
    C++ 遇见的一些函数
    C++ #pragma 预处理指令
    C++异常处理(Exception Handling)
    C++模板学习随笔
    C++ 数组的地址问题学习随笔
    关于C++几个容易混淆的概念总结
  • 原文地址:https://www.cnblogs.com/lhm-/p/14322164.html
Copyright © 2011-2022 走看看