二维数据结构学习

/*
感觉noip不会靠这些东西..但是碰见了不看看就觉得很别扭,本来想大体知道就行了,背个板,然后 我一下午+一晚上就没干别的QAQ
先说说线段树吧 处理二维问题的有两种方法 树套树和四叉树
后者好理解常数小但是不资次打标记(反正我不会~~~)
后者XXXX常熟大但是资次打标记(我也不会~~~)
只看看前面那个 树套树嘛 就是在一维的基础上 每个节点都连出一棵树来
空间复杂度n*n 因为他不支持打标记 所以不能区间改 区间查 
只能区间改 单点查 或者单点改 区间查
再啦啦树状数组 同样的 必须扯着一个单点
区间改的时候 可以向上或者向下更新 查询的时候正好反着
基础的东西就这么多了 也没准备学的很详细
*/

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*
poj 2155
第一个二维线段树的题
树套树写法 不支持打标记
(四叉树支持 然而并不会QAQ) 
所以这个区间修改就和之前的不大一样
准确的说这导致只能单点查询
查单点的时候 把路径上的遇到的标记累加
因为没有下传 所以都加起来
还有就是 Query的时候 不是找到x这一行在进入第二层线段树
而是每个第一层的区间(前提是包含x)都进入第二层y区间找 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
#define lc k*2
#define rc k*2+1
#define mid (l+r)/2
using namespace std;
int T,n,m,x1,x2,y1,y2,num;
bool s[maxn*4][maxn*4];
char c[5];
void Changey(int kx,int k,int l,int r,int x,int y){
    if(x<=l&&y>=r){
        s[kx][k]=!s[kx][k];
        return;
    }
    if(l==r)return;
    if(x<=mid)Changey(kx,lc,l,mid,x,y);
    if(y>mid)Changey(kx,rc,mid+1,r,x,y);
}
void Changex(int k,int l,int r,int x,int y){
    if(x<=l&&y>=r){
        Changey(k,1,1,n,y1,y2);
        return;
    }
    if(l==r)return;
    if(x<=mid)Changex(lc,l,mid,x,y);
    if(y>mid)Changex(rc,mid+1,r,x,y);
}
void Queryy(int kx,int k,int l,int r,int x){
    num+=s[kx][k];
    if(l==r)return;
    if(x<=mid)return Queryy(kx,lc,l,mid,x);
    else return Queryy(kx,rc,mid+1,r,x);
}
void Queryx(int k,int l,int r,int x){
    Queryy(k,1,1,n,y1);
    if(l==r)return;
    if(x<=mid)return Queryx(lc,l,mid,x);
    else return Queryx(rc,mid+1,r,x);
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n*4;i++)
            for(int j=1;j<=n*4;j++)
                s[i][j]=0;
        while(m--){
            scanf("%s",c);
            if(c[0]=='C'){
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                Changex(1,1,n,x1,x2);
            }
            else {
                num=0;
                scanf("%d%d",&x1,&y1);
                Queryx(1,1,n,x1);
                printf("%d
",num&1);
            }
        }
        printf("
");
    }
    return 0;
}
/*
之前树状数组的了解不全面啊
一直以为只能单点修改区间查询
今天又学到了区间修改单点查询
二维的也是一样
改的时候用矩形右下角代表整个矩形改没改过
然后把多改的改回来
单点查询的时候向下询问 累加 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int T,n,m,x1,x2,y1,y2;
int s[maxn][maxn];
char c[5];
int low(int x){
    return x&(-x);
}
void Insert(int x,int y){
    for(int i=x;i>0;i-=low(i))
        for(int j=y;j>0;j-=low(j))
            s[i][j]++;
}
int Query(int x,int y){
    int ret=0;
    for(int i=x;i<=n+2;i+=low(i))
        for(int j=y;j<=n+2;j+=low(j))
            ret+=s[i][j];
    return ret;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n+2;i++)
            for(int j=1;j<=n+2;j++)
                s[i][j]=0;
        while(m--){
            scanf("%s",c);
            if(c[0]=='C'){
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                x1+=2;x2+=2;y1+=2;y2+=2;
                Insert(x2,y2);Insert(x1-1,y1-1);
                Insert(x2,y1-1);Insert(x1-1,y2);
            }
            else {
                scanf("%d%d",&x1,&y1);
                x1+=2;y1+=2;
                int num=Query(x1,y1);
                printf("%d
",num&1);
            }
        }
        printf("
");
    }
    return 0;
}
/*hud1823*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1001
#define lc k*2
#define rc k*2+1
#define mid (l+r)/2
using namespace std;
int n=1000,m,x1,y1,x2,y2;
short int mx[maxn*3][maxn*4],z;
char c[5];
void Insert_y(int kx,int k,int l,int r){
    mx[kx][k]=max(mx[kx][k],z);
    if(l==r)return;
    if(y1<=mid)Insert_y(kx,lc,l,mid);
    else Insert_y(kx,rc,mid+1,r);
    mx[kx][k]=max(mx[kx][lc],mx[kx][rc]);
}
void Insert_x(int k,int l,int r){
    Insert_y(k,1,0,n);
    if(l==r)return;
    if(x1<=mid)Insert_x(lc,l,mid);
    else Insert_x(rc,mid+1,r);
}
int Query_y(int kx,int k,int l,int r){
    if(y1<=l&&y2>=r)return mx[kx][k];
    if(y2<=mid)return Query_y(kx,lc,l,mid);
    else if(y1>mid)return Query_y(kx,rc,mid+1,r);
    else return max(Query_y(kx,lc,l,mid),Query_y(kx,rc,mid+1,r));
}
int Query_x(int k,int l,int r){
    if(x1<=l&&x2>=r)return Query_y(k,1,0,n);
    if(x2<=mid)return Query_x(lc,l,mid);
    else if(x1>mid)return Query_x(rc,mid+1,r);
    else return max(Query_x(lc,l,mid),Query_x(rc,mid+1,r));
}
int main()
{
    while(1){
        scanf("%d",&m);
        if(m==0)break;
        memset(mx,-1,sizeof(mx));
        float xi,yi,h1,h2;
        int h;
        while(m--){
            scanf("%s",c);
            if(c[0]=='I'){
                scanf("%d%f%f",&h,&xi,&yi);
                x1=h;y1=int(xi*10);z=int(yi*10);
                Insert_x(1,0,n);
            }
            else {
                scanf("%f%f%f%f",&h1,&h2,&xi,&yi);
                x1=int(h1+0.9);x2=int(h2+0.9);
                y1=int(xi*10);y2=int(yi*10);
                if(x1>x2)swap(x1,x2);
                if(y1>y2)swap(y1,y2);
                int ans=Query_x(1,0,n);
                if(ans==-1)printf("-1
");
                else printf("%.1f
",ans/10.0);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yanlifneg/p/5910746.html