zoukankan      html  css  js  c++  java
  • BZOJ4066: 简单题

    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。
    接下来每行一个操作。每条命令除第一个数字之外,
    均要异或上一次输出的答案last_ans,初始时last_ans=0。
     

    Output

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

    Sample Input

    4
    1 2 3 3
    2 1 1 3 3
    1 1 1 1
    2 1 1 0 7
    3

    Sample Output

    3
    5

    HINT

    数据规模和约定

    1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。

    样例解释见OJ2683
    新加数据一组,但未重测----2015.05.24

    隔壁AKC一眼CDQ发现是在线又一眼树套树发现MLE了。。

    实在不是很会搞,分割平面那就KD-tree走一波

    至于加值,那就是插点,查找就类似于线段树维护下子树和不行递归找

    然后T掉了:多次加点使树的结构失衡,退化为平方级算法

    那就暴力重构,每到一定范围就像替罪羊树一样强行拆开重构

    //MT_LI
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    struct KDT{
        int lc,rc,s,sum;
        int mn[2],mx[2],d[2];
    }tr[500010];
    void update(int x)
    {
        int lc=tr[x].lc,rc=tr[x].rc;
        if(lc)
        {
            tr[x].mn[0]=min(tr[x].mn[0],tr[lc].mn[0]);
            tr[x].mn[1]=min(tr[x].mn[1],tr[lc].mn[1]);
            tr[x].mx[0]=max(tr[x].mx[0],tr[lc].mx[0]);
            tr[x].mx[1]=max(tr[x].mx[1],tr[lc].mx[1]);
            tr[x].sum+=tr[lc].sum;
        }
        if(rc)
        {
            tr[x].mn[0]=min(tr[x].mn[0],tr[rc].mn[0]);
            tr[x].mn[1]=min(tr[x].mn[1],tr[rc].mn[1]);
            tr[x].mx[0]=max(tr[x].mx[0],tr[rc].mx[0]);
            tr[x].mx[1]=max(tr[x].mx[1],tr[rc].mx[1]);
            tr[x].sum+=tr[rc].sum;
        }
    }
    int cmpd,root;
    bool cmp(KDT a,KDT b){return a.d[cmpd]<b.d[cmpd] || a.d[cmpd]==b.d[cmpd]&&a.d[cmpd^1]<b.d[cmpd^1];}
    void ins(int now)
    {
        int p=root;
        while(1)
        {
            if(tr[p].mx[0]<tr[now].mx[0])tr[p].mx[0]=tr[now].mx[0];
            if(tr[p].mx[1]<tr[now].mx[1])tr[p].mx[1]=tr[now].mx[1];
            if(tr[p].mn[0]>tr[now].mn[0])tr[p].mn[0]=tr[now].mn[0];
            if(tr[p].mn[1]>tr[now].mn[1])tr[p].mn[1]=tr[now].mn[1];
            tr[p].sum+=tr[now].sum;
            if(tr[now].d[cmpd]<tr[p].d[cmpd])
            {
                if(tr[p].lc==0){tr[p].lc=now;return ;}
                else p=tr[p].lc;
            }
            else
            {
                if(tr[p].rc==0){tr[p].rc=now;return ;}
                else p=tr[p].rc;
            }
            cmpd^=1;
        }
    }
    int find(int x,int x1,int y1,int x2,int y2)
    {
        if(tr[x].mn[0]>x2||tr[x].mn[1]>y2||tr[x].mx[0]<x1||tr[x].mx[1]<y1)return 0;
        if(tr[x].mx[0]<=x2&&tr[x].mx[1]<=y2&&tr[x].mn[0]>=x1&&tr[x].mn[1]>=y1)return tr[x].sum;
        int tot=0;
        if(tr[x].d[0]>=x1&&tr[x].d[1]>=y1&&tr[x].d[0]<=x2&&tr[x].d[1]<=y2)tot=tr[x].s;
        if(tr[x].lc)tot+=find(tr[x].lc,x1,y1,x2,y2);
        if(tr[x].rc)tot+=find(tr[x].rc,x1,y1,x2,y2);
        return tot;
    }
    int rebuild(int l,int r,int d)
    {
        int mid=(l+r)/2,now;
        now=mid;cmpd=d;
        nth_element(tr+l,tr+mid,tr+r+1,cmp);
        tr[now].mx[0]=tr[now].mn[0]=tr[now].d[0];
        tr[now].mx[1]=tr[now].mn[1]=tr[now].d[1];
        tr[now].sum=tr[now].s;
        if(l<mid)tr[now].lc=rebuild(l,mid-1,d^1);
        if(mid<r)tr[now].rc=rebuild(mid+1,r,d^1);
        update(now);
        return now;
    }
    int ans=0;
    int main()
    {
        int n;int cnt=0;
        scanf("%d",&n);root=0;
        while(1)
        {
            int op;
            scanf("%d",&op);
            if(op==3)break;
            if(op==1)
            {
                ++cnt;
                scanf("%d%d%d",&tr[cnt].d[0],&tr[cnt].d[1],&tr[cnt].s);
                tr[cnt].d[0]^=ans;tr[cnt].d[1]^=ans;tr[cnt].s^=ans;
                tr[cnt].mx[0]=tr[cnt].mn[0]=tr[cnt].d[0];
                tr[cnt].mx[1]=tr[cnt].mn[1]=tr[cnt].d[1];
                tr[cnt].sum=tr[cnt].s;
                if(cnt%10000==0)
                {
                    for(int i=1;i<=cnt;i++)tr[i].lc=tr[i].rc=0;
                    root=rebuild(1,cnt,0);
                    continue;
                }
                if(root==0)root=cnt;
                else cmpd=0,ins(cnt);
            }
            else
            {
                int x1,x2,y1,y2;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                x1^=ans;x2^=ans;y1^=ans;y2^=ans;
                ans=find(root,x1,y1,x2,y2);
                printf("%d
    ",ans);            
            }
        }
        return 0;
    }
  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9791657.html
Copyright © 2011-2022 走看看