首页 > 代码库 > 线段树专题

线段树专题

HDU 1754 I Hate It

  点更新+段查询

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 200000+10;
int n,num[maxn],m;
struct node{
    int lson,rson;
    int mid(){
        return lson+(rson-lson)/2;
    }
    int maxx;
}tree[maxn*3];
void pushup(int rt){
    tree[rt].maxx = max(tree[rt<<1].maxx,tree[rt<<1|1].maxx);
}
void build(int l,int r,int root){
    tree[root].lson = l;
    tree[root].rson = r;
    if(l==r) {
        tree[root].maxx = num[l];
        return;
    }
    int mid = tree[root].mid();
    build(l,mid,root<<1);
    build(mid+1,r,root<<1 | 1);
    pushup(root);
}

void update(int pos,int val,int rt){
    if(tree[rt].lson==tree[rt].rson){
       tree[rt].maxx = val;
       return;
    }
    int mid =tree[rt].mid();
    if(pos <= mid) update(pos,val,rt<<1);
    else update(pos,val,rt<<1|1);
    pushup(rt);
}
int query(int L,int R,int root){
    if(L<=tree[root].lson&&tree[root].rson<=R)
        return tree[root].maxx;
    int mid = tree[root].mid();
    if(mid >= R) {
        return query(L,R,root*2);
    }
    else if(mid < L){
        return query(L,R,root*2+1);
    }
    else{
        return max(query(L,R,root*2),query(L,R,root*2+1));
    }
}
int main(){

    while(cin >> n >> m){
        for(int i = 1; i <= n; i++) scanf("%d",&num[i]);
        build(1,n,1);
        char op;
        int a,b;
        while(m--){
            cin >> op;
            if(op==‘Q‘){
                scanf("%d%d",&a,&b);
                cout << query(a,b,1)<<endl;
            }else{
                scanf("%d%d",&a,&b);
                update(a,b,1);
            }
        }
    }
    return 0;
}

HDU 1698 Just a Hook

成段更新

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 100000+10;
struct node{
    int lson,rson;
    int mid(){
        return lson + (rson-lson)/2;
    }
    int sum,lazy;
}tree[maxn*4];
int n,m;

void pushup(int rt){
    tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
}

void pushdown(int rt){
    if(tree[rt].lazy > 0){
        tree[rt<<1].lazy = tree[rt<<1|1].lazy = tree[rt].lazy;
        tree[rt<<1].sum = (tree[rt<<1].rson-tree[rt<<1].lson+1)*tree[rt].lazy;
        tree[rt<<1|1].sum = (tree[rt<<1|1].rson-tree[rt<<1|1].lson+1)*tree[rt].lazy;
        tree[rt].lazy = 0;
    }
}

void build(int l,int r,int rt){
    tree[rt].lson = l;
    tree[rt].rson = r;
    tree[rt].lazy = 0;
    if(l==r){
        tree[rt].sum = 1;
        return;
    }
    int mid = tree[rt].mid();
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}

void update(int L,int R,int rt,int lazy){
    if(L<=tree[rt].lson&&tree[rt].rson<=R){
        tree[rt].lazy = lazy;
        tree[rt].sum = lazy*(tree[rt].rson-tree[rt].lson+1);
        return;
    }
    pushdown(rt);
    int mid = tree[rt].mid();
    if(L <= mid)    update(L,R,rt<<1,lazy);

    if(R > mid)     update(L,R,rt<<1|1,lazy);

    pushup(rt);
}

int main(){
    int ncase,T=1;
    cin >> ncase;
    while(ncase--){
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            update(a,b,1,c);
        }
        printf("Case %d: The total value of the hook is %d.\n",T++,tree[1].sum);
    }
    return 0;
}

HDU1394 Minimum Inversion Number

逆序数问题。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxn = 5000+10;
int n,num[maxn],m;
struct node{
    int lson,rson;
    int mid(){
        return lson + (rson-lson)/2;
    }
    int sum;
}tree[maxn*4];

void pushup(int rt){
    tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;
}

void build(int l,int r,int rt){
    tree[rt].lson = l;
    tree[rt].rson = r;
    tree[rt].sum = 0;
    if(l==r)  return;
    int mid = tree[rt].mid();
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1 | 1);
}

void update(int pos,int rt){
        if(tree[rt].lson==tree[rt].rson){
             tree[rt].sum++;
             return;
        }
        int mid = tree[rt].mid();
        if(pos<=mid)    update(pos,rt<<1);
        else    update(pos,rt<<1|1);
        pushup(rt);
}

int query(int L,int R,int rt){
    if(L<=tree[rt].lson&&tree[rt].rson<=R)
        return tree[rt].sum;
    int mid = tree[rt].mid();
    int res = 0;
    if(L <= mid) res += query(L,R,rt<<1);
    if(R > mid) res  += query(L,R,rt<<1|1);
    return res;
}

int main(){

    while(cin >> n){
        build(0,n-1,1);
        int res = 0;
        for(int i = 0; i < n; i++){
            scanf("%d",&num[i]);
            res += query(num[i],n-1,1);
            update(num[i],1);
        }
        int ans = res;
        for(int i = 0; i < n; i++){
            res += n-num[i]*2-1;
            ans = min(ans,res);
        }
        cout<<ans<<endl;
    }
    return 0;
}


HDU1542  Atlantis

扫描线

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 100000+10;
struct line{
    double x,bot,up;
    int flag;
    line(double x,double bot,double up,int flag):x(x),bot(bot),up(up),flag(flag){}
    friend bool operator <(line a,line b){
        return a.x < b.x;
    }
};
vector<line> vl;
vector<double> vd;
int n;
struct node{
    double lson,rson;
    double x;
    int cover;
    int flag;
    int mid(){
        return lson + (rson-lson)/2;
    }
}tree[maxn*4];

void build(int l,int r,int rt){
    tree[rt].lson = vd[l];
    tree[rt].x = -1;
    tree[rt].rson = vd[r];
    tree[rt].cover = 0;
    tree[rt].flag = 0;
    if(l+1==r){
        tree[rt].flag = 1;
        return;
    }
    int mid =(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid,r,rt<<1|1);
}

double insert(double x,double bot,double top,int cnt,int rt){
    if(tree[rt].lson  >= top || tree[rt].rson <= bot) return 0;
    if(tree[rt].flag){
        if(tree[rt].cover>0){
            double t = tree[rt].x,ans=0;
            ans = (x-t)*(tree[rt].rson-tree[rt].lson);
            tree[rt].x = x;
            tree[rt].cover += cnt;
            return ans;
        }else{
            tree[rt].x = x;
            tree[rt].cover += cnt;
            return 0;
        }
    }
    return insert(x,bot,top,cnt,rt<<1)+insert(x,bot,top,cnt,rt<<1|1);
}
int main(){

    int T=1;
    while(cin >> n && n){
        vl.clear();
        vd.clear();
        for(int i = 0; i < n; i++){
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            vl.push_back(line(x1,y1,y2,1));
            vl.push_back(line(x2,y1,y2,-1));
            vd.push_back(y1);
            vd.push_back(y2);
        }
        sort(vd.begin(),vd.end());
        sort(vl.begin(),vl.end());
        build(0,vl.size()-1,1);
        double ans = 0;
        for(int i = 0; i < vl.size(); i++){
            ans += insert(vl[i].x,vl[i].bot,vl[i].up,vl[i].flag,1);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n",T++,ans);
        cout<<endl;
    }
    return 0;
}

HDU 1264 Counting Squares

扫描线

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 100+10;
struct node{
    int x,lson,rson;
    int len,cover;
    int mid(){
        return lson + (rson-lson)/2;
    }
}tree[maxn*6];
struct line{
    int x,y1,y2;
    int flag;
    friend bool operator <(line a,line b){
        return a.x < b.x;
    }
    line(int x,int y1,int y2,int flag):x(x),y1(y1),y2(y2),flag(flag){}
};
vector<line> vl;
void pushup(int rt){
    if(tree[rt].cover){
        tree[rt].len = tree[rt].rson+1-tree[rt].lson;
        return;
    }
    tree[rt].len = tree[rt<<1].len + tree[rt<<1|1].len;
}
void build(int l,int r,int rt){
    tree[rt].lson = l;
    tree[rt].rson = r;
    tree[rt].cover = 0;
    tree[rt].len = 0;
    if(l==r) return;
    int mid = tree[rt].mid();
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
}
void update(int L,int R,int rt,int flag){
    if(L <= tree[rt].lson && tree[rt].rson <= R){
        tree[rt].cover += flag;
        pushup(rt);
        return;
    }
    int mid = tree[rt].mid();
    if(L <= mid)   update(L,R,rt<<1,flag);
    if(R > mid) update(L,R,rt<<1|1,flag);
    pushup(rt);
}
int main(){

    int x1,y1,x2,y2;
    int t=0;
    while(1){
        vl.clear();
        while(~scanf("%d%d%d%d",&x1,&y1,&x2,&y2)){
            if(x1==-1&&x2==-1&&y1==-1&&y2==-1){
                break;
            }
            if(x1==-2&&y1==-2&&x2==-2&&y2==-2){
                t = 1;
                break;
            }
            if(x1 > x2) swap(x1,x2);
            if(y1 > y2) swap(y1,y2);
            vl.push_back(line(x1,y1,y2,1));
            vl.push_back(line(x2,y1,y2,-1));
        }
        build(0,maxn,1);
        sort(vl.begin(),vl.end());
        int ans = 0;
        for(int i = 0; i < vl.size()-1; i++){
            int L = vl[i].y1;
            int R = vl[i].y2-1;
            update(L,R,1,vl[i].flag);
            ans += (vl[i+1].x-vl[i].x)*tree[1].len;
        }
        cout<<ans<<endl;
        if(t)   break;

    }
    return 0;
}