您的位置:首页 > 其它

AC题目简解-线段树

2014-02-28 13:54 183 查看
线段树:

http://www.notonlysuccess.com/index.php/segment-tree-complete/
鉴于notonlysuccess大牛的博客对于题目的思路写的很简陋,我就稍微补充下。
线段树的基本内容,是通过建二叉树来实现段的存储,最下面的叶子节点是每个值,左孩子和右孩子的父亲则是这个段的信息,依次推上去,实现从1..n的存储。可以通过程序带入样例来模拟这个过程体会。
建树:非叶子节点存储的都是段的值,而每个段,都有一个左边界和右边界。那么就建到叶子节点为止。每次都二分这个段,最后肯定会左边界等于右边界。
更新:如果是点更新则判断点即可,只是在判断该点在哪个区间的时候注意,一下。
查询:查询和更新类似
注意每一个return。
敌兵布阵:很简单的查询和单点更新





#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=50010;
int n;
struct node{
    int data,left,right;
    void init(int aleft,int aright){
        left=aleft;
        right=aright;
        data=0;
    }
}tree[MAXN<<2];
void pushup(int id){
    tree[id].data=tree[id<<1].data+tree[id<<1|1].data;
}
void build(int left,int right,int id){
    tree[id].init(left,right);
    if(left==right){
        scanf("%d",&tree[id].data);
        return;//remember here!
    }
    int mid=(left+right)>>1;
    build(left,mid,id<<1);
    build(mid+1,right,id<<1|1);
    pushup(id);
}
int query(int left,int right,int id){
    if(left==tree[id].left&&right==tree[id].right)return tree[id].data;
    int mid=(tree[id].left+tree[id].right)>>1;
    if(right<=mid)return query(left,right,id<<1);
    else
        if(left>mid)return query(left,right,id<<1|1);
        else
            return query(left,mid,id<<1)+query(mid+1,right,id<<1|1);
}
void update(int p,int vadd,int id){
    if(tree[id].left==tree[id].right){
        tree[id].data+=vadd;
        return ;
    }
    int mid=(tree[id].left+tree[id].right)>>1;
    if(p<=mid) update(p,vadd,id<<1);
    else update(p,vadd,id<<1|1);
    pushup(id);
}
int main(){
    int t,a,b;
    scanf("%d",&t);
    char op[10];
    for(int i=1;i<=t;i++){
        printf("Case %d:\n",i);
        scanf("%d",&n);
        build(1,n,1);
        while(scanf("%s",op)&&op[0]!='E'){
            scanf("%d%d",&a,&b);
            switch(op[0]){
            case 'Q':printf("%d\n",query(a,b,1));break;
            case 'A':update(a,b,1);break;
            case 'S':update(a,-b,1);break;
            }
        }
    }
    return 0;
}


View Code

hdu1754 I Hate It :单点替换,注意pushup上去





#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=200010;
struct node{
    int data,left,right;
    void init(int aleft,int aright){
        left=aleft;right=aright;
        data=0;
    }
};
node tree[MAXN<<2];
inline void pushup(int id){
    tree[id].data=max(tree[id<<1].data,tree[id<<1|1].data);
}
void build(int left,int right,int id){
    tree[id].init(left,right);//this
    if(left==right){
        scanf("%d",&tree[id].data);
        return;
    }
    int mid=(left+right)>>1;
    build(left,mid,id<<1);
    build(mid+1,right,id<<1|1);
    pushup(id);
}
void update(int p,int value,int id){
    if(tree[id].left==tree[id].right){
        tree[id].data=value;
        return;
    }
    int mid=(tree[id].left+tree[id].right)>>1;
    if(p<=mid)update(p,value,id<<1);
    else update(p,value,id<<1|1);
    pushup(id);

}
int query(int left,int right,int id){
    if(left==tree[id].left&&right==tree[id].right)return tree[id].data;
    int mid=(tree[id].left+tree[id].right)>>1;
    if(right<=mid)return query(left,right,id<<1);
    else
        if(left>mid)return query(left,right,id<<1|1);
        else
            return max(query(left,mid,id<<1),query(mid+1,right,id<<1|1));

}
int main(){
    int n,m,a,b;
    char op[2];
    while(scanf("%d%d",&n,&m)!=EOF){
        build(1,n,1);
        for(int i=0;i<m;i++){
            scanf("%s%d%d",&op,&a,&b);
            if(op[0]=='Q')printf("%d\n",query(a,b,1));
            else update(a,b,1);
        }
    }

    return 0;
}


View Code


hdu1394 Minimum Inversion Number 题意:求Inversion后的最小逆序数可以看看这篇博客
http://www.cnblogs.com/ziyi--caolu/archive/2013/01/15/2860768.html




#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=5005;
struct node{
    int left,right,data;
    void init(int aleft,int aright){
        left=aleft;
        right=aright;
        data=0;//the num of the value before it
    }
};
node tree[MAXN<<2];
int n,a[MAXN];
inline void pushup(int id){
    tree[id].data=tree[id<<1].data+tree[id<<1|1].data;
}
void build(int left,int right,int id){
    tree[id].init(left,right);
    if(left==right)return;
    int mid=(left+right)>>1;
    build(left,mid,id<<1);
    build(mid+1,right,id<<1|1);
}
void update(int p,int id){
    if(tree[id].left==tree[id].right){
        tree[id].data=1;
        return;
    }
    int mid=(tree[id].left+tree[id].right)>>1;
    if(p<=mid)update(p,id<<1);
    else update(p,id<<1|1);
    pushup(id);
}

int query(int k,int id){
    if(k>tree[id].right)return 0;
    if(k<=tree[id].left)return tree[id].data;
    int mid=(tree[id].left+tree[id].right)>>1;
    return query(k,id<<1)+query(k,id<<1|1);
}
int main(){
    while(scanf("%d",&n)!=EOF){
        build(0,n-1,1);
        int ans=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            ans+=query(a[i],1);
            update(a[i],1);
        }
        int minx=ans;
        for(int i=0;i<n;i++){
            ans+=n-2*a[i]-1;
            if(ans<minx)minx=ans;
        }
        printf("%d\n",minx);
    }
    return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: