• 【BZOJ2683】简单题


    2683: 简单题

    Time Limit: 50 Sec  Memory Limit: 128 MB
    Submit: 1268  Solved: 502
    [Submit][Status][Discuss]

    Description

    你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

    命令

    参数限制

    内容

    1 x y A

    1<=x,y<=N,A是正整数

    将格子x,y里的数字加上A

    2 x1 y1 x2 y2

    1<=x1<= x2<=N

    1<=y1<= y2<=N

    输出x1 y1 x2 y2这个矩形内的数字和

    3

    终止程序

    Input

    输入文件第一行一个正整数N。
    接下来每行一个操作。
     

    Output

    对于每个2操作,输出一个对应的答案。
     

    Sample Input

    4
    1 2 3 3
    2 1 1 3 3
    1 2 2 2
    2 2 2 3 4
    3

    Sample Output

    3
    5

    HINT

    1<=N<=500000,操作数不超过200000个,内存限制20M。

    对于100%的数据,操作1中的A不超过2000。

    Source

    显然这题不能树套树 原因自己看数据范围

    那我们怎么做?

    cdq分治

    不过我还没有看懂到底是怎么个做法

    反正肯定是这样的:

    对时间分治,像归并排序一样考虑[l,mid]对[mid+1,r]的影响(问题1:如何处理影响?)

    由于我们读入的时候肯定是x是连续的,所以我们一次可以处理很多询问(问题2:询问如何处理?)

    所以我们最后只用维护一下树状数组就可以得到答案(问题3:为什么?)

    这里先放上代码 明天我去问一下机房的大神得到这三个问题的答案

    /*To The End Of The Galaxy*/
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<iomanip>
    #include<stack>
    #include<map>
    #include<set>
    #include<cmath>
    #include<complex>
    #define debug(x) cerr<<#x<<"="<<x<<endl
    #define INF 0x7f7f7f7f
    #define llINF 0x7fffffffffffll
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    inline int init()
    {
        int now=0,ju=1;char c;bool flag=false;
        while(1)
        {
            c=getchar();
            if(c=='-')ju=-1;
            else if(c>='0'&&c<='9')
            {
                now=now*10+c-'0';
                flag=true;
            }
            else if(flag)return now*ju;
        }
    }
    inline long long llinit()
    {
        long long now=0,ju=1;char c;bool flag=false;
        while(1)
        {
            c=getchar();
            if(c=='-')ju=-1;
            else if(c>='0'&&c<='9')
            {
                now=now*10+c-'0';
                flag=true;
            }
            else if(flag)return now*ju;
        }
    }
    int n,m;
    struct node
    {
        int t,x,y,d,id,v;
    }query[2000005],tmpq[2000005];
    int ans[2000005],s[2000005];
    bool operator < (node a,node b)
    {
        if(a.x!=b.x)
        {
            return a.x<b.x;
        }
        else return a.y<b.y;
    }
    #define lowbit(x) (x&(-x))
    void Add(int now,int v)
    {
        for(int i=now;i<=n;i+=lowbit(i))
        {
            s[i]+=v;
        }
    }
    int Query(int now)
    {
        int sum=0;
        for(int i=now;i>=1;i-=lowbit(i))
        {
            sum+=s[i];
        }
        return sum;
    }
    #define mid ((l+r)>>1)
    void solve(int l,int r)
    {
        if(l==r)return;
        solve(l,mid);solve(mid+1,r);
        int i=l,j=mid+1,last=0;
        while(j<=r)
        {
            while(i<=mid&&query[i].t==2)
            {
                i++;
            }
            while(j<=r&&query[j].t==1)
            {
                j++;
            }
            if(i<=mid&&query[i].x<=query[j].x)
            {
                Add(query[i].y,query[i].v);
                last=i;
                i++;
            }
            else if(j<=r)ans[query[j].id]+=Query(query[j].y),j++;
        }
        for(int i=l;i<=last;i++)
        {
            if(query[i].t==1)
            {
                Add(query[i].y,-query[i].v);
            }
        }
        merge(query+l,query+1+mid,query+1+mid,query+1+r,tmpq+l);
        for(int i=l;i<=r;i++)
        {
            query[i]=tmpq[i];
        }
        return;
    }
    bool cmpid(node a,node b)
    {
        return a.id<b.id;
    }
    int c[2000005],tot=0;
    int main()
    {
        n=init();
        int xl,xr,yl,yr,v,type;
        while(type=init(),type!=3)
        {
            if(type==1)
            {
                xl=init();yl=init();v=init();
                ++m;
                query[m].x=xl;query[m].y=yl;query[m].v=v;query[m].t=type;query[m].id=m;
            }
            else if(type==2)
            {
                c[++tot]=m;
                xl=init();yl=init();xr=init();yr=init();
                ++m;
                query[m].id=m;query[m].x=xr;query[m].y=yr;query[m].t=type;
                ++m;
                query[m].id=m;query[m].x=xl-1;query[m].y=yl-1;query[m].t=type;
                ++m;
                query[m].id=m;query[m].x=xl-1;query[m].y=yr;query[m].t=type;
                ++m;
                query[m].id=m;query[m].x=xr;query[m].y=yl-1;query[m].t=type;
            }
        }
        int p;
        solve(1,m);
        for(int i=1;i<=tot;i++)
        {
            printf("%d
    ",ans[c[i]+1]+ans[c[i]+2]-ans[c[i]+3]-ans[c[i]+4]);
        }
        return 0;
    }
    /*
    srO xudyh davidlee1999WTK linkct1999 Orz
    compiler TDM-GCC 5.9.2
    */
    View Code

     UPD:

    cdq分治是这样一种东西

    首先我们将x1,x2,y1,y2的询问拆分成

    [1,x1-1] 贡献为1

    [1,y1-1] 贡献为1

    [1,x2]贡献为-1

    [1,y1-1]贡献为-1

    [1,x1-1]贡献为-1

    [1,y2]贡献为-1

    ……

    画个图直观显示一下 就是这样

    我们将一个查询分成了四个 然后是用树状数组维护

    然后对时间分治,由于分治的思想我们自然能保证所有的[l,mid]的询问都已经处理过了,且所有[mid+1,r]的修改都已经处理过了

    现在我们考虑如何合并

    首先我们最后要将这些东西按照x轴归并 这是显然的 不然我们无法保证顺序

    那么我们实际上维护了三维偏序集

    所以说,我们这样做

    我们像归并排序那样维护twopointer,由于我们[l,mid]中的修改,x必然是连续的,[mid+1,r]中的修改,x也必然是连续的

    我们就只剩下y轴要考虑了,我们对y轴维护前缀和,具体来说我们用树状数组/线段树维护

    由于我们这个时候已经是既按照时间顺序又按照x轴顺序了,那么我们从l到mid的过程中,我们只要看一下右边的x是否还有贡献

     大概就是这样……我也不是特别懂

  • 相关阅读:
    TCP并发服务器(一)——每个客户一个子进程
    TCP并发服务器(六)——创建线程池,每个线程accept,accept使用互斥锁保护——基于UNP代码
    TCP并发服务器(七)——可动态增减的线程池,主线程accept——基于UNP代码修改
    STL源码之vector
    coffee-script安装
    Python模块包中__init__.py文件的作用
    原型模式
    facade模式
    类继承模式
    备忘模式
  • 原文地址:https://www.cnblogs.com/redwind/p/6503642.html
Copyright © 2020-2023  润新知