乱七八糟的树状数组和线段树

2024-03-30 06:38

本文主要是介绍乱七八糟的树状数组和线段树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

//

//  main.cpp

//  线段树rmq

//

//  Created by liuzhe on 16/10/29.

//  Copyright © 2016 my_code. All rights reserved.

//


/*

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;


int max_,min_;


struct node

{

    int l,r;

    int max_,min_;

}segtree[800005];

int a[200005];


void build(int i,int l,int r)

{

    segtree[i].l = l;

    segtree[i].r = r;

    if(l == r)

    {

        segtree[i].min_ = segtree[i].max_ = a[l];

        return;

    }

    int mid = (l+r)/2;

    build(i<<1,l,mid);

    build(i<<1|1,mid+1,r);

    segtree[i].min_=min(segtree[i<<1].min_,segtree[i<<1|1].min_);

    segtree[i].max_=max(segtree[i<<1].max_,segtree[i<<1|1].max_);

}


void query(int i,int l,int r)

{

    if(segtree[i].max_<=max_&&segtree[i].min_>=min_)

        return ;

    if(segtree[i].l == l &&segtree[i].r == r)

    {

        max_=max(segtree[i].max_,max_);

        min_=min(segtree[i].min_,min_);

        return ;

    }

    int mid = (segtree[i].l+segtree[i].r)>>1;

    if(r<=mid)

        query(i<<2,l,r);

    else

        if(l>mid)

            query(i<<1|1,l,r);

    else

    {

        query(i<<1,l,mid);

        query(i<<1|1,mid+1,r);

    }

}


int main(int argc, const char * argv[]) {

    // insert code here...

    int n,q;

    int l,r;

    while(cin>>n>>q)

    {

        for(int i=1;i<=n;++i)

            scanf("%d",&a[i]);

        for(int j=1;j<=q;j++)

        {

            scanf("%d%d",&l,&r);

            max_=-99999999;

            min_=99999999;

            query(1,l,r);

            printf("%d\n",max_-min_);

        }

    }

    

    //std::cout << "Hello, World!\n";

    return 0;

}*/


#include <vector>

#include <map>

#include <set>

#include <algorithm>

#include <iostream>

#include <cstdio>

#include <cmath>

#include <cstdlib>

#include <string>

#include <cstring>

#include <cstdio>

#include <algorithm>

#include <iostream>

#include <cstring>

#include <string>

#include <cmath>

using namespace std;

/*

#define MAXN 200005

#define INF 10000000

int nMax,nMin;//记录最大最小值

struct Node

{

    int l,r;//区间的左右端点

    int nMin,nMax;//区间的最小值和最大值

}segTree[MAXN*3];

int a[MAXN];

void Build(int i,int l,int r)//在结点i上建立区间为(l,r)

{

    segTree[i].l=l;

    segTree[i].r=r;

    if(l==r)//叶子结点

    {

        segTree[i].nMin=segTree[i].nMax=a[l];

        return;

    }

    int mid=(l+r)>>1;

    Build(i<<1,l,mid);

    Build(i<<1|1,mid+1,r);

    segTree[i].nMin=min(segTree[i<<1].nMin,segTree[i<<1|1].nMin);

    segTree[i].nMax=max(segTree[i<<1].nMax,segTree[i<<1|1].nMax);

}

void Query(int i,int l,int r)//查询结点il-r的最大值和最小值

{

    if(segTree[i].nMax<=nMax&&segTree[i].nMin>=nMin)  return;

    if(segTree[i].l==l&&segTree[i].r==r)

    {

        nMax=max(segTree[i].nMax,nMax);

        nMin=min(segTree[i].nMin,nMin);

        return;

    }

    int mid=(segTree[i].l+segTree[i].r)>>1;

    if(r<=mid)   Query(i<<1,l,r);

    else if(l>mid)  Query(i<<1|1,l,r);

    else

    {

        Query(i<<1,l,mid);

        Query(i<<1|1,mid+1,r);

    }

}

int main()

{

    int n,q;

    int l,r;

    int i;

    while(scanf("%d%d",&n,&q)!=EOF)

    {

        for(i=1;i<=n;i++)

            scanf("%d",&a[i]);

        Build(1,1,n);

        for(i=1;i<=q;i++)

        {

            scanf("%d%d",&l,&r);

            nMax=-INF;nMin=INF;

            Query(1,l,r);

            printf("%d\n",nMax-nMin);

        }

    }

    return 0;

}

 */


//模板

/*

int lowbit(int x)

{

    return x & (-x);

}

//modify函数是将第x位的值增加add

void modify(int x,int add)//一维

{

    while(x<=MAXN)

    {

        a[x]+=add;

        x+=lowbit(x);

    }

}

int get_sum(int x)

{

    int ret=0;

    while(x!=0)

    {

        ret+=a[x];

        x-=lowbit(x);

    }

    return ret;

}

void modify(int x,int y,int data)//二维

{

    for(int i=x;i<MAXN;i+=lowbit(i))

        for(int j=y;j<MAXN;j+=lowbit(j))

            a[i][j]+=data;

}

//get_sum是询问1到当前x的区间

int get_sum(int x,int y)

{

    int res=0;

    for(int i=x;i>0;i-=lowbit(i))

        for(int j=y;j>0;j-=lowbit(j))

            res+=a[i][j];

    return res;

}

 */


/*

int n,tree[100005];


int lowbit(int i)

{

    return i & (-i);

}


void update(int i,int x)

{

    for(;i<=n;i+=lowbit(i))

        tree[i]+=x;

    //while(i<=n)

    //{

      //  tree[i]+=x;

        //i+=lowbit(i);

    //}

}


int query(int n)

{

    int sum=0;

    for(;n>0;n-=lowbit(n))

        sum+=tree[n];

    return sum;

}


int main()

{

    int t;

    cin>>t;

    for(int cas=1;cas<=t;cas++)

    {

        memset(tree,0,sizeof(tree));

        cout<<"Case "<<cas<<':'<<endl;

        scanf("%d",&n);

        for(int i=1;i<=n;i++)

        {

            int x;

            scanf("%d",&x);

            update(i,x);

        }

        char s[10];

        while(scanf("%s",s)!=-1&&strcmp(s,"End"))

        {

            int a,b;

            scanf("%d%d",&a,&b);

            if(s[0]=='Q')

                printf("%d\n",query(b)-query(a-1));

            else

                if(s[0]=='S')

                    update(a,-b);

            else

                update(a,b);

        }

        

    }

    

    return 0;

}


 */



/*

//int tree[1005];

long long n,m,k,t;

long long tr[1000005];

struct node

{

    long long s,e;

}tree[1000005];


long long cmp(node a,node b)

{

    if(a.s!=b.s)

        return (a.s)<(b.s);

    else

        return (a.e)<(b.e);

}


long long lowbit(long long i)

{

    return i&(-i);

}


void update(long long i,long long x)

{

    for(;i<=k;i+=lowbit(i))

        tr[i]+=x;

}


long long query(long long n)

{

    long long sum=0;

    for(;n>0;n-=lowbit(n))

        sum+=tr[n];

    return sum;

}



int main()

{

    cin>>t;

    for(long long cas=1;cas<=t;cas++)

    {

        long long ans = 0;

        memset(tree,0,sizeof(tree));

        memset(tr,0,sizeof(tr));

        cin>>n>>m>>k;

        for(long long i=1;i<=k;i++)

            scanf("%lld%lld",&tree[i].e,&tree[i].s);

        sort(tree+1,tree+1+k,cmp);

        //for(int i=1;i<=k;i++)

          //  cout<<tree[i].s<<' '<<tree[i].e<<endl;

        //    tr[i]=tree[i].e;

        for(long long i=1;i<=k;i++)

        {

            long long a=tree[i].e;

            update(a,1);

            ans+=(query(m)-query(a));

        }

        printf("Test case %lld: ",cas);

        printf("%lld\n",ans);

    }

    

    return 0;

}

*/


/*


#define lowbit(x) (x&-x)

const int N=1000005;

struct node

{

    int l,r,id;

} a[N];

int n,c[N],x,y;


int cmp(node a,node b)

{

    if(a.l!=b.l)

        return a.l<b.l;

    return a.r<b.r;

}


int sum(int x)

{

    int ret = 0;

    while(x>0)

    {

        ret+=c[x];

        x-=lowbit(x);

    }

    return ret;

}


void add(int x,int d)

{

    while(x<=y)

    {

        c[x]+=d;

        x+=lowbit(x);

    }

}


long long ans;

int main()

{

    int i,j,k,l,r,t,cas = 1;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d%d",&x,&y,&n);

        

        memset(c,0,sizeof(c));

        for(i = 1; i<=n; i++)

        {

            scanf("%d%d",&a[i].l,&a[i].r);

        }

        sort(a+1,a+1+n,cmp);

        ans = 0;

        for(i = 1; i<=n; i++)

        {

            add(a[i].r,1);

            ans+=sum(y)-sum(a[i].r);

        }

        printf("Test case %d: %lld\n",cas++,ans);

    }

    

    return 0;

}

*/


/*


//int num[100005];

int a,b,x;


struct Tree

{

    int l,r,num,lazy;

}

tree[400005];


void build(int root,int l,int r)

{

    tree[root].l=l;

    tree[root].r=r;

    tree[root].num = r-l+1;

    tree[root].lazy=1;

    if(l==r)

    {

        //tree[root].sum=num[l];

        return;

    }

    int mid = (l+r)/2;

    build(root<<1,l,mid);

    build(root<<1|1,mid+1,r);

    //tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;

}


void update(int root,int x,int y,int val)

{

    int ll,rr;

    ll=tree[root].l;

    rr=tree[root].r;

    if(ll==x&&rr==y)

    {

        tree[root].lazy=1;

        tree[root].num=(rr-ll+1)*val;

        return ;

    }

    int mid = (tree[root].r+tree[root].l)>>1;

    if(tree[root].lazy)

    {

        tree[root].lazy=0;

        update(root<<1,ll,mid,tree[root].num*(rr-ll+1));

        update(root<<1|1,mid,rr,tree[root].num*(rr-ll+1));

    }

    if(x<=mid)

        update(root<<1,x,min(mid,y),val);

    if(y>=mid)

        update(root<<1|1,max(mid+1,x),y,val);

    tree[root].num=tree[root<<1].num+tree[root<<1|1].num;

    //tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;

}


int query(int root)

{

    //if(l<=tree[root].l&&r>=tree[root].r)

      //  return tree[root].sum;

    //int mid = (tree[root].l+tree[root].r)>>1,ret=0;

    //if(l<=mid)

      //  ret+=query(root<<1,l,r);

    //if(r>mid)

      //  ret+=query(root<<1|1,l,r);

    //return ret;

    if(tree[root].lazy)

        return tree[root].num;

    return query(root<<1)+query(root<<1|1);

}


int main()

{

    int ca,cas=1;

    int n,t;

    cin>>ca;

    while(ca--)

    {

        cin>>n>>t;

        //for(int i=1;i<=n;i++)

        //memset(num,1,sizeof(num));

        build(1,1,n);

        printf("Case %d: The total value of the hook is ",cas++);

        while(t--)

        {

            scanf("%d%d%d",&a,&b,&x);

            //for(int j=a;j<=b;j++)

                update(1,a,b,x);

            //update(1,b,x);

            //update(1,(a-1),-x);

        }

        printf("%d\n",query(1));

    }

    return 0;

}


 */


/*

 

 typedef struct

 {

 int l,r,num,lazy;

 }Tree;

 

 Tree tree[500005];

 

 void Build(int t,int l,int r)

 {

 int mid;

 tree[t].l=l;

 tree[t].r=r;

 tree[t].num=r-l+1;

 tree[t].lazy=1;

 if (l==r) return;

 mid=(l+r)/2;

 Build(2*t+1,l,mid);

 Build(2*t+2,mid+1,r);

 }

 

 void Add(int t,int x,int y,int c)

 {

 int mid,l,r;

 l=tree[t].l;

 r=tree[t].r;

 if (l==x && r==y)

 {

 tree[t].lazy=1;

 tree[t].num=(r-l+1)*c;

 return;

 }

 mid=(l+r)/2;

 if (tree[t].lazy==1)

 {

 tree[t].lazy=0;

 Add(2*t+1,l,mid,tree[t].num/(r-l+1));

 Add(2*t+2,mid+1,r,tree[t].num/(r-l+1));

 }

 if (x<=mid) Add(2*t+1,x,min(mid,y),c);

 if (y>mid) Add(2*t+2,max(mid+1,x),y,c);

 tree[t].num=tree[2*t+1].num+tree[2*t+2].num;

 }

 

 int Find(int t)

 {

 if (tree[t].lazy==1) return tree[t].num;

 return Find(2*t+1)+Find(2*t+2);

 }

 

 int main()

 {

 int i,j,n,T,m,x,y,c,cnt=1;

 scanf("%d",&T);

 while(T--)

 {

 scanf("%d",&n);

 Build(0,0,n-1);

 scanf("%d",&m);

 while(m--)

 {

 scanf("%d%d%d",&x,&y,&c);

 Add(0,x-1,y-1,c);

 }

 printf("Case %d: The total value of the hook is %d.\n",cnt++,Find(0));

 }

 return 0;

 }

 

 1

 10

 2

 1 5 2

 5 9 3

*/


/*

int n,tree[500005];


int an[500005];


struct node

{

    int v,order;

}in[500005];


int lowbit(int i)

{

    return i & (-i);

}


void update(int i,int x)

{

    for(;i<=n;i+=lowbit(i))

        tree[i]+=x;

}


int query(int n)

{

    int sum=0;

    for(;n>0;n-=lowbit(n))

        sum+=tree[n];

    return sum;

}


bool cmp(node a,node b)

{

    return a.v<b.v;

}


int main()

{

    while(cin>>n&&n)

    {

        long long ans=0;

        memset(tree,0,sizeof(tree));

        for(int i=1;i<=n;i++)

        {

            scanf("%d",&in[i].v);

            in[i].order=i;

        }

        sort(in+1,in+1+n,cmp);

        for(int i=1;i<=n;i++)

            an[in[i].order]=i;

        for(int i=1;i<=n;i++)

        {

            update(an[i],1);

            ans+=i-query(an[i]);

        }

        printf("%lld\n",ans);

    }

    

    return 0;

}

*/


/*

 说明:

 1. rtLR都是从1开始计数;

 2. 线段树的空间应当是原数组的四倍;(最小应该为,向上取到最近的二的次幂,再乘以2)

 3. 每次调用buildqueryupdate时,LR应该是整个区间(1-N),一般写成query(1,1,N)

 */

/*

#define lson rt<<1,L,M

#define rson rt<<1|1,M+1,R

#define maxn 2000000 + 10


int sumv[maxn<<2]; //树上结点

int lazy[maxn<<2];//仅当区间更新时使用,点更新不需要

void pushUp(int rt) {

    sumv[rt] = sumv[rt<<1] | sumv[rt<<1|1];

}


//区间更新时才需要使用pushDown

void pushDown(int rt) {  //len在主函数里一般为 r - l +

    lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];  // lazy标记向两个儿子传递

    sumv[rt<<1] = lazy[rt]; // 更新左儿子sumv

    sumv[rt<<1|1] = lazy[rt];     // 更新右儿子sumv

    lazy[rt] = 0;                            // 向下传递完后清空当前结点lazy标记

}


void build(int rt, int L, int R) {

    int M = (L+R) >> 1;

    if (L == R) {

        sumv[rt] = 2; //始化线段树。

    } else {

        build(lson);

        build(rson);

        pushUp(rt);

    }

}


//区间更新

void update(int tl, int tr, int v, int rt, int L, int R){

    int M = (L+R)>>1;

    if (tl<=L && R<=tr) {

        lazy[rt] = v;

        sumv[rt] = v;

    } else {

        if (lazy[rt]) pushDown(rt, R-L+1);

        if (tl <= M) update(tl, tr, v, lson);

        if (tr >= M+1) update(tl, tr, v, rson);

        pushUp(rt);

    }

}


int query(int tl, int tr, int rt, int L, int R) {

    int M = (L+R) >> 1;

    int ret = 0;

    if (lazy[rt]) pushDown(rt, R-L+1);

    if (tl<=L && R<=tr) return sumv[rt]; // 查询区间涵盖了整个区间

    if (tl <= M) ret |= query(tl, tr, lson); // 查询区间在左边有分布

    if (M < tr) ret |= query(tl, tr, rson); // 查询区间在右边有分布

    return ret;

}


int main(){

    int n,m;

    while(scanf("%d%d",&n,&m) != EOF)

    {

        memset(lazy,0,sizeof(lazy));

        if (n == 0 && m == 0) break;

        build(1,1,n);

        while(m--)

        {

            char ch;

            scanf("%*c%c",&ch);

            if (ch == 'P')

            {

                int x,y,value;

                scanf("%d%d%d",&x,&y,&value);

                update(x,y,1 << (value - 1),1,1,n);

            }

            else

            {

                int x,y;

                scanf("%d%d",&x,&y);

                int ans = query(x,y,1,1,n);

                int first = 1;

                for (int i = 1; i <= 32; i++)

                {

                    if (ans & 1)

                    {

                        if (first)

                        {

                            first = 0;

                            printf("%d",i);

                        }

                        else

                        {

                            printf(" %d",i);

                        }

                    }

                    ans >>= 1;

                }

                printf("\n");

            }

        }

    }

    return 0;

}

*/



/*

int level[40005],sum[40005];

//sum[i]中装的是x不大于i的点的个数


int lowbit(int i)

{

    return i&(-i);

}


int getsum(int i)

{

    int s=0;

    for(;i>0;i-=lowbit(i))

        s+=sum[i];

    return s;

}


void update(int x)

{

    while(x<40005)

    {

        sum[x]++;

        x+=lowbit(x);

    }

}


int main()

{

    int n,x,y;

    while(scanf("%d",&n)!=-1)

    {

        memset(sum,0,sizeof(sum));

        memset(level,0,sizeof(level));

        for(int i=0;i<n;i++)

        {

            scanf("%d%d",&x,&y);

            level[getsum(x+1)]++;

            update(x+1);

        }

        for(int i=0;i<n;++i)

            printf("%d\n",level[i]);

    }

    

    

    return 0;

}

*/









/*

const int N = 1000010;

struct tree{

    int lp,rp,minvalue,maxvalue;

    int getmid(){

        return (lp + rp) / 2;

    }

}tt[N * 4];


struct ans{

    int minans,maxans;

}aa[N];

int num[N];


void built_tree(int lp,int rp,int pos){

    tt[pos].lp = lp;

    tt[pos].rp = rp;

    int mid = tt[pos].getmid();

    if(lp == rp){

        tt[pos].minvalue = tt[pos].maxvalue = num[lp];

        return;

    }

    built_tree(lp,mid,pos*2);

    built_tree(mid+1,rp,pos*2+1);

    tt[pos].minvalue = min(tt[pos*2].minvalue,tt[pos*2+1].minvalue);

    tt[pos].maxvalue = max(tt[pos*2].maxvalue,tt[pos*2+1].maxvalue);

}


int query(int lp,int rp,int pos ,int id){

    if(tt[pos].lp == lp && tt[pos].rp == rp){

        if(id == 0)

            return tt[pos].minvalue;

        else

            return tt[pos].maxvalue;

    }

    int mid = tt[pos].getmid();

    if(mid >= rp)

        return query(lp,rp,pos*2,id);

    else if(mid < lp)

        return query(lp,rp,pos*2+1,id);

    else{

        if(id == 0)

            return min(query(lp,mid,pos*2,id),query(mid+1,rp,pos*2+1,id));

        else

            return max(query(lp,mid,pos*2,id),query(mid+1,rp,pos*2+1,id));

    }

}


int main(){

    int n,m;

    while(scanf("%d%d",&n,&m) != EOF){

        for(int i = 1; i <= n; ++i)

            scanf("%d",&num[i]);

        built_tree(1,n,1);

        for(int i = 1; i <= n - m + 1; ++i){

            int j = i + m - 1;

            aa[i].minans = query(i,j,1,0);

            aa[i].maxans = query(i,j,1,1);

        }

        for(int i = 1; i < n - m + 1; ++i)

            printf("%d ",aa[i].minans);

        printf("%d\n",aa[n-m+1].minans);

        for(int i = 1; i < n - m + 1; ++i)

            printf("%d ",aa[i].maxans);

        printf("%d\n",aa[n-m+1].maxans);

    }

    return 0;  

}  

*/




/*

const int N=1000005;

struct Tree{

    int l,r,minvalue,maxvalue;

};


Tree tree[4*N];


struct Ans{

    int minans,maxans;

};

Ans ans[N];


int num[N];


void buildtree(int root,int l,int r)

{

    tree[root].l=l;

    tree[root].r=r;

    int mid=(tree[root].l+tree[root].r)>>1;

    if(l==r)

    {

        tree[root].minvalue = tree[root].maxvalue = num[l];

        return ;

    }

    buildtree(root<<1,l,mid);

    buildtree(root<<1|1,mid+1,r);

    tree[root].maxvalue=max(tree[root<<1].maxvalue,tree[root<<1|1].maxvalue);

    tree[root].minvalue=min(tree[root<<1].minvalue,tree[root<<1|1].minvalue);

}


int query(int l,int r,int root,int flag)

{

    if(tree[root].l==l&&r==tree[root].r)

    {

        if(flag)

            return tree[root].maxvalue;

        else

            return tree[root].minvalue;

    }

    int mid = (tree[root].l+tree[root].r)>>1;

    if(r<=mid)

    {

        return query(l,r,root<<1,flag);

    }

    else

        if(l>mid)

        {

            return query(l,r,root<<1|1,flag);

        }

    else

        if(flag)

            return max(query(l,mid,root<<1,flag),query(mid+1,r,root<<1|1,flag));

    else

        return min(query(l,mid,root<<1,flag),query(mid+1,r,root<<1|1,flag));

}



int main()

{

    int n,m;

    while(scanf("%d%d",&n,&m)!=-1)

    {

        for(int i=1;i<=n;i++)

            scanf("%d",&num[i]);

        buildtree(1,1,n);

        for(int i=1;i<=n-m+1;i++)

        {

            ans[i].maxans=query(i,i+m-1,1,1);//1代表大

            ans[i].minans=query(i,i+m-1,1,0);//0代表小

        }

        for(int i=1;i<=n-m+1;++i)

            printf("%d ",ans[i].minans);

        printf("\n");

        for(int i=1;i<=n-m+1;++i)

            printf("%d ",ans[i].maxans);

        printf("\n");

    }

    return 0;

}

*/


/*

const int maxn=1000011;

struct Node{

    int l,r,root,min,max;

}tree[maxn*5];

int minl[maxn],maxl[maxn],a[maxn],k,len;

void build(int l,int r,int root){

    tree[root].l=l;

    tree[root].r=r;

    if(l==r){

        tree[root].min=tree[root].max=a[l];

        return;

    }

    int mid=(l+r)>>1;

    build(l,mid,root*2);

    build(mid+1,r,root*2+1);

    tree[root].min=min(tree[root*2].min,tree[root*2+1].min);

    tree[root].max=max(tree[root*2].max,tree[root*2+1].max);

}

bool init(){

    if(scanf("%d",&k)==EOF)return false;

    scanf("%d",&len);

    for(int i=1;i<=k;i++)scanf("%d",&a[i]);

    build(1,k,1);

    return true;

}

void query(int l,int r,int &min,int &max,int root){

    if(tree[root].l==l&&tree[root].r==r){

        min=tree[root].min;

        max=tree[root].max;

        return;

    }

    int mid=(tree[root].l+tree[root].r)>>1;

    if(mid>=r)query(l,r,min,max,root*2);

    else if(mid<l)query(l,r,min,max,root*2+1);

    else{

        int max2,min2;

        query(l,mid,min,max,root*2);

        query(mid+1,r,min2,max2,root*2+1);

        min=min<min2?min:min2;

        max=max>max2?max:max2;

    }

}

void work(){

    int ans1,ans2,i;

    for(i=1;i<=k-len+1;i++){

        query(i,i+len-1,ans2,ans1,1);

        minl[i]=ans2;

        maxl[i]=ans1;

    }

}

void print(){

    int i;

    for(i=1;i<=k-len+1;i++)printf("%d ",minl[i]);

    cout<<endl;

    for(i=1;i<=k-len+1;i++)printf("%d ",maxl[i]);

    cout<<endl;

}

int main(){

    while(init()){

        work();

        print();

    }

    return 0;

}

*/



/*

int n,cnt;

const int maxn = 100010;

struct node

{

    int l,r,n;//n统计颜色

};

node a[maxn<<2];


struct  qujian

{

    int point;//point纪录去见的边

    int num;//num记录位置

};

qujian s[maxn<<2];


int Map[maxn<<1][2];

int ans;

int flag[maxn<<1];


int cmp(qujian a,qujian b)

{

    return a.point<b.point;

}


void init(int l,int r,int i)//建树

{

    a[i].l=l;

    a[i].r=r;

    a[i].n=0;

    if(l!=r)

    {

        int mid = (l+r)>>1;

        init(l,mid,i<<1);

        init(mid+1,r,i<<1|1);

    }

}


void update(int i,int l,int r,int m)

{

    if(a[i].l==l&&a[i].r==r)

    {

        a[i].n=m;

        return ;

    }

    int mid=(a[i].l+a[i].r)>>1;

    if(a[i].n>0)//重点:如果这个区间访问过了,而且这个区间没有颜色

        //就要将这个区间的颜色更新到其左右孩子的节点,并且要将个

        //区间的颜色清空,才算是覆盖。

    {

        a[i<<1].n=a[i<<1|1].n=a[i].n;

        a[i].n=0;

    }

    if(r<=a[i*2].l)

        update(i<<1,l,r,m);

    else

        if(l>a[i<<1|1].l)

            update(i<<1|1,l,r,m);

        else

    {

        update(i<<1,l,mid,m);

        update(i<<1|1,mid+1,r,m);

    }

}


void query(int i)

{

    if(a[i].n)

    {

        if(!flag[a[i].n])

        {

            ans++;

            flag[a[i].n]=1;

        }

        return ;

    }

    query(i<<1);

    query(i<<1|1);

    return ;

}


int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        scanf("%d",&n);

        for(int i=0;i<n;i++)//离散化

        {

            scanf("%d%d",&Map[i][0],&Map[i][1]);

            s[i<<1].point = Map[i][0];

            s[i<<1|1].point = Map[i][1];

            s[i<<1].num=-i-1;

            s[i<<1|1].num=i+1;

        }

        sort(s,s+n*2,cmp);

        int tmp = s[0].point;

        cnt = 1;

        for(int i=0;i<n<<1;i++)

        {

            if(tmp!=s[i].point)//和前面的不同,迭代加一

            {

                cnt++;

                tmp=s[i].point;

            }

            if(s[i].num>=0)

                Map[s[i].num-1][1] = cnt;

            else

                Map[-s[i].num-1][0]=cnt;

        }

        init(1,cnt,1);

        for(int i=0;i<n;i++)

        {

            update(1,Map[i][0],Map[i][1],i+1);

        }

        memset(flag,0,sizeof(flag));

        ans=0;

        query(1);

        cout<<ans<<endl;

    }

    return 0;

}

 */




int n,m;

int c[1005][1005];


int lowbit(int i)

{

    return i&(-1);

}


int sum(int i,int j)

{

    int ans=0;

    for(;i>0;i-=lowbit(i))

        for(;j>0;j-=lowbit(j))

            ans += c[i][j];

    return ans;

}


void query(int i,int j)

{

    for(;i<=n;i+=lowbit(i))

        for(;j<=n;j+=lowbit(j));

    c[i][j]++;

}


int main()

{

    int X;

    cin>>X;

    while(X--)

    {

        scanf("%d%d",&n,&m);

        memset(c,0,sizeof(c));

        while(m--)

        {

            getchar();

            char s;

            scanf("%c",&s);

            if(s=='C')

            {

                int x1,y1,x2,y2;

                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);

                query(x2+1,y2+1);

                query(x1,y1);

                query(x2+1,y1);

                query(x1,y2+1);

            }

            else

            {

                int x1,y1;

                scanf("%d%d",&x1,&y1);

                x1++;

                y1++;

                printf("%d\n",sum(x1,y1)%2);

            }

        }

        printf("\n");

    }

    return 0;

}

         









这篇关于乱七八糟的树状数组和线段树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860750

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

HDU4737线段树

题目大意:给定一系列数,F(i,j)表示对从ai到aj连续求或运算,(i<=j)求F(i,j)<=m的总数。 const int Max_N = 100008 ;int sum[Max_N<<2] , x[Max_N] ;int n , m ;void push_up(int t){sum[t] = sum[t<<1] | sum[t<<1|1] ;}void upd

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

圆与线段的交点

poj 3819  给出一条线段的两个端点,再给出n个圆,求出这条线段被所有圆覆盖的部分占了整条线段的百分比。 圆与线段的交点 : 向量AB 的参数方程  P = A + t * (B - A)      0<=t<=1 ; 将点带入圆的方程即可。  注意: 有交点 0 <= t <= 1 ; 此题求覆盖的部分。 则 若求得 t  满足 ; double ask(d