kuangbin专题七:线段树

  终于到专题七了。

 

HDU1166 敌兵布阵

思路:线段树模板题。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 5e4 + 5;
int val[maxn];

struct Node{
    int l, r, val;
} node[maxn * 4];

void pushup(int idx){
    node[idx].val = node[idx << 1].val + node[idx << 1 | 1].val;
}

void build(int l, int r, int idx){
    if(l >= r){
        node[idx] = {l, r, val[l]};
    }
    else{
        int mid = (l + r) >> 1;
        node[idx] = {l, r, 0};
        build(l, mid, idx << 1), build(mid + 1, r, idx << 1 | 1);
        pushup(idx);
    }
}

void update(int pos, int val, int idx){
    if(node[idx].r == node[idx].l && node[idx].l == pos){
        node[idx].val += val;
    }
    else{
        int mid = (node[idx].l + node[idx].r) >> 1;
        if(pos <= mid) update(pos, val, idx << 1);
        else update(pos, val, idx << 1 | 1);
        pushup(idx);
    }
}

int query(int l, int r, int idx){
    if(l <= node[idx].l && node[idx].r <= r) return node[idx].val;

    int res = 0;
    int mid = (node[idx].l + node[idx].r) >> 1;
    if(l <= mid) res += query(l, r, idx << 1);
    if(r > mid) res += query(l, r, idx << 1 | 1);
    return res;
}

int main(){
    int T;
    scanf("%d", &T);
    for(int t = 1; t <= T; t++){
        printf("Case %d:\n", t);
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &val[i]);

        build(1, n, 1);

        string op;
        while(cin >> op && op != "End"){
            int l, r;
            scanf("%d%d", &l, &r);

            if(op == "Query") printf("%d\n", query(l, r, 1));
            else if(op == "Add") update(l, r, 1);
            else update(l, -r, 1);
        }
    }
    return 0;
}
View Code

 

HDU1754 I Hate It

思路:模板题。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 2e5 + 5;
int score[maxn], maxScore[maxn * 4];

void pushup(int idx){
    maxScore[idx] = max(maxScore[idx<<1], maxScore[idx<<1|1]);
}

void build(int idx, int l, int r){
    if(l == r){
        maxScore[idx] = score[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(idx << 1, l, mid), build(idx << 1 | 1, mid + 1, r);
    pushup(idx);
}

void update(int idx, int l, int r, int x, int v){
    if(l == r){
        maxScore[idx] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) update(idx << 1, l, mid, x, v);
    else update(idx << 1 | 1, mid + 1, r, x, v);
    pushup(idx);
}

int query(int idx, int l, int r, int x, int y){
    if(x <= l && r <= y) return maxScore[idx];
    int mid = (l + r) >> 1, ans = -1;
    if(x <= mid) ans = max(ans, query(idx << 1, l, mid, x, y));
    if(mid < y) ans = max(ans, query(idx << 1 | 1, mid + 1, r, x, y));
    return ans;
}

int main(){
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF){
        for(int i = 1; i <= n; i++) scanf("%d", &score[i]);
        build(1, 1, n);

        char op;
        int A, B;
        while(m--){
            scanf(" %c%d%d", &op, &A, &B);
            if(op == 'Q') printf("%d\n", query(1, 1, n, A, B));
            else update(1, 1, n, A, B);
        }
    }
    return 0;
}
View Code

 

POJ3468 A Simple Problem with Integers

 思路:模板题,注意push down。

#include <iostream>
#include <stdio.h>
using namespace std;
const int MAXN = 1e5 + 10;
long long sum[MAXN << 2];
long long w[MAXN << 2];

void push_up(int idx){
    sum[idx] = sum[idx << 1] + sum[idx << 1 | 1];
}

void push_down(int idx, int m){
    if(w[idx]){
        w[idx << 1] += w[idx];
        w[idx << 1 | 1] += w[idx];
        sum[idx << 1] += (m - (m >> 1)) * w[idx];
        sum[idx << 1 | 1] += (m >> 1) * w[idx];
        w[idx] = 0;
    }
}

void build(int idx, int l, int r){
    w[idx] = 0;
    if(l == r){
        scanf("%lld", &sum[idx]);
        return;
    }
    int mid = (l + r) >> 1;
    build(idx << 1, l, mid);
    build(idx << 1 | 1, mid + 1, r);
    push_up(idx);
}

void update(int idx, int l, int r, int L, int R, long long value){
    if(L <= l && R >= r){
        sum[idx] += (r - l + 1) * value;
        w[idx] += value;
        return;
    }
    push_down(idx, r - l + 1);
    int mid = (l + r) >> 1;
    if(L <= mid) update(idx << 1, l, mid, L, R, value);
    if(R > mid) update(idx << 1 | 1, mid + 1, r, L, R, value);
    push_up(idx);
}

long long query(int idx, int l, int r, int L, int R){
    if(L <= l && R >= r) return sum[idx];
    push_down(idx, r - l + 1);
    int mid = (l + r) >> 1;
    long long ans = 0;
    if(L <= mid) ans += query(idx << 1, l, mid, L, R);
    if(R > mid) ans += query(idx << 1 | 1, mid + 1, r, L, R);
    return ans;
}

int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    build(1, 1, n);
    while(m--){
        char str[3];
        int x, y;
        long long z;
        scanf("%s", str);
        if(str[0] == 'C'){
            scanf("%d%d%lld", &x, &y, &z);
            update(1, 1, n, x, y, z);
        }else{
            scanf("%d%d", &x, &y);
            printf("%lld\n", query(1, 1, n, x, y));
        }
    }
}
View Code

 

POJ2528 Mayor's posters

思路:乱七八糟的题目,乱七八糟的解法。自己的代码一直WA,对着以前抄的AC代码也WA。。。。把以前代码贴上。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 10000 + 5;
int n, t;
int vis[maxn<<3], sum[maxn<<4];
int li[maxn<<1], ri[maxn<<1], lsh[maxn<<2];

void pushdown(int rt){
    sum[rt<<1] = sum[rt];
    sum[rt<<1|1] = sum[rt];
    sum[rt] = -1;
}

void update(int L, int R, int C, int l, int r, int rt){
    if(L<=l && r<=R){
        sum[rt] = C;
        return;
    }
    if(sum[rt]!=-1) pushdown(rt);
    int m = (l+r)>>1;
    if(m>=R) update(L, R, C, l, m, rt<<1);
    else if(L > m) update(L, R, C, m+1, r, rt<<1|1);
    else update(L, m, C, l, m, rt<<1), update(m+1, R, C, m+1, r, rt<<1|1);
}

int ans;
void  query(int l, int r, int rt){
    if(!vis[sum[rt]]&&sum[rt]!=-1){
        ans++;
        vis[sum[rt]] = 1;
        return;
    }
    if(l == r) return;
    if(sum[rt] != -1)
        pushdown(rt);
    int m = (l+r) >> 1;
    query(l, m, rt<<1);
    query(m+1, r, rt<<1|1);
}

int main(){
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        memset(sum, -1, sizeof(sum));
        memset(vis, 0, sizeof(sum));
        int tot = 0;
        for(int i = 0; i < n; i++){
            scanf("%d%d", &li[i], &ri[i]);
            lsh[tot++] = li[i];
            lsh[tot++] = ri[i];
        }
        sort(lsh, lsh+tot);
        int mm = unique(lsh, lsh+tot) - lsh;
        int tt = mm;
        for(int i = 1; i < tt; i++)
            if(lsh[i]-lsh[i-1] > 1)
                lsh[mm++] = lsh[i-1]+1;
        sort(lsh, lsh+mm);
        for(int i = 0; i < n; i++){
            int x = lower_bound(lsh, lsh+mm, li[i]) - lsh;
            int y = lower_bound(lsh, lsh+mm, ri[i]) - lsh;
            update(x, y, i, 0, mm-1, 1);
        }
        ans = 0;
        query(0, mm-1, 1);
        printf("%d\n", ans);
    }

    return 0;
}
View Code

 

HDU1698 Just a Hook

思路:模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int tree[maxn << 2];

void build(int idx, int l, int r){
    if(l == r){
        tree[idx] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(idx << 1, l, mid);
    build(idx << 1 | 1, mid + 1, r);
    tree[idx] = 1;
}

void pushdown(int idx){
    tree[idx << 1] = tree[idx << 1 | 1] = tree[idx];
}

void update(int idx, int l, int r, int L, int R, int meta){
    if(L <= l && r <= R){
        tree[idx] = meta;
        return;
    }
    if(tree[idx] != -1)
        pushdown(idx);
    int mid = (l + r) >> 1;
    if(L <= mid) update(idx << 1, l, mid, L, R, meta);
    if(mid < R) update(idx << 1 | 1, mid + 1, r, L, R, meta);
    tree[idx] = tree[idx << 1] == tree[idx << 1 | 1] ? tree[idx << 1] : -1;
}

int query(int idx, int l, int r){
    if(tree[idx] != -1)
        return tree[idx] * (r - l + 1);
    int mid = (l + r) >> 1, ans = 0;
    ans += query(idx << 1, l, mid);
    ans += query(idx << 1 | 1, mid + 1, r);
    return ans;
}

int main(){
    int T;
    scanf("%d", &T);
    for(int t = 1; t <= T; t++){
        int n, m;
        scanf("%d%d", &n, &m);

        build(1, 1, n);
        for(int i = 0; i < m; i++){
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            update(1, 1, n, x, y, z);
        }
        printf("Case %d: The total value of the hook is %d.\n", t, query(1, 1, n));
    }
    return 0;
}
View Code

 

POJ3264 Balanced Lineup

思路:模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#define lc(root) (root << 1)
#define rc(root) (root << 1 | 1)
using namespace std;
const int maxn = 5e4 + 5;

struct Tree{
    int mn, mx;
} tree[maxn << 2];

void pushup(int root){
    tree[root].mn = min(tree[lc(root)].mn, tree[rc(root)].mn);
    tree[root].mx = max(tree[lc(root)].mx, tree[rc(root)].mx);
}

void build(int root, int l, int r){
    if(l == r){
        int val;
        scanf("%d", &val);
        tree[root].mn = tree[root].mx = val;
        return;
    }
    int mid = (l + r) >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
    pushup(root);
}

Tree query(int root, int l, int r, int L, int R){
    if(L <= l && r <= R){
        Tree ans = {tree[root].mn, tree[root].mx};
        return ans;
    }
    int mid = (l + r) >> 1;
    Tree ans = {0x3f3f3f3f, 0};
    if(L <= mid){
        Tree res = query(root << 1, l, mid, L, R);
        ans.mn = min(ans.mn, res.mn);
        ans.mx = max(ans.mx, res.mx);
    }
    if(mid < R){
        Tree res = query(root << 1 | 1, mid + 1, r, L, R);
        ans.mn = min(ans.mn, res.mn);
        ans.mx = max(ans.mx, res.mx);
    }
    return ans;
}

int main(){
    int N, Q;
    scanf("%d%d", &N, &Q);
    build(1, 1, N);
    for(int i = 0; i < Q; i++){
        int A, B;
        scanf("%d%d", &A, &B);
        Tree ans = query(1, 1, N, A, B);
        printf("%d\n", ans.mx - ans.mn);
    }
    return 0;
}
View Code

 

HDU4027 Can you answer these queries?

思路:注意优化,算是比较坑的一题,但是学到了新的码风。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
#define mid ((l + r) >> 1)
#define lc (root << 1)
#define rc (root << 1 | 1)
using namespace std;
const int maxn = 1e5 + 5;
LL tree[maxn << 2];

void build(int root, int l, int r){
    if(l == r) return void(scanf("%lld", &tree[root]));
    build(lc, l, mid); build(rc, mid + 1, r);
    tree[root] = tree[lc] + tree[rc];
}

void update(int root, int l, int r, int L, int R){
    if(l > R || r < L || tree[root] == (r - l + 1)) return;
    if(l == r) return void(tree[root] = sqrt(tree[root]));
    update(lc, l, mid, L, R), update(rc, mid + 1, r, L, R);
    tree[root] = tree[lc] + tree[rc];
}

LL query(int root, int l, int r, int L, int R){
    if(l > R || r < L) return 0;
    if(L <= l && r <= R) return tree[root];
    return query(lc, l, mid, L, R) + query(rc, mid + 1, r, L, R);
}

int main(){
    int T = 0;
    int n, m;
    while(scanf("%d", &n) != EOF){
        printf("Case #%d:\n", ++T);
        build(1, 1, n);
        scanf("%d", &m);
        for(int i = 0; i < m; i++){
            int op, x, y;
            scanf("%d%d%d", &op, &x, &y);
            if(x > y) x ^= y ^= x ^= y;
            if(op == 0) update(1, 1, n, x, y);
            else printf("%lld\n", query(1, 1, n, x, y));
        }
        printf("\n");
    }
    return 0;
}
View Code

 

HDU 1540 Tunnel Warfare

思路:线段树有点复杂,网上的一个算法比较好,是用红黑树解决的,题目数据有点弱。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<stack>
#define LL long long
using namespace std;

int main(){
    int n, m, x;
    char c;
    while(scanf("%d%d", &n, &m) != EOF){
        stack<int> stk;
        set<int> st;
        st.insert(0), st.insert(n + 1);
        while(m--){
            getchar();
            scanf("%c", &c);
            if(c == 'R') st.erase(stk.top()), stk.pop();
            else{
                scanf("%d", &x);
                if(c == 'D') st.insert(x), stk.push(x);
                else if(st.find(x) != st.end()) printf("0\n");
                else{
                    auto l = st.lower_bound(x), r = st.upper_bound(x);
                    printf("%d\n", *r-*--l-1);
                }
            }
        }
    }
    return 0;
}
View Code

 

HDU3974 Assign the task

思路:建树,每个employee指向直接boss。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 5e4 + 5;
int n, m;
int boss[maxn];
int tasks[maxn], sq[maxn];

void update(int e, int t, int id){
    tasks[e] = t;
    sq[e] = id;
}

void query(int e){
    int b = e, t = e;
    while(boss[b]){
        if(sq[boss[b]] > sq[t]) t = boss[b];
        b = boss[b];
    }
    printf("%d\n", tasks[t]);
}

int main(){
    int T;
    scanf("%d", &T);
    for(int t = 1; t <= T; t++){
        scanf("%d", &n);
        memset(boss, 0, sizeof(boss));
        for(int i = 0; i < n-1; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            boss[u] = v;
        }

        printf("Case #%d:\n", t);
        scanf("%d", &m);
        memset(tasks, -1, sizeof(tasks));
        memset(sq, 0, sizeof(sq));
        for(int i = 1; i <= m; i++){
            char op[2];
            int x, y;
            scanf("%s", op);
            if(op[0] == 'C'){
                scanf("%d", &x);
                query(x);
            }
            else{
                scanf("%d%d", &x, &y);
                update(x, y, i);
            }
        }
    }
    return 0;
}
View Code

 

HDU4578 Transformation

思路:题目比较烦,抄了其它人的暴力解法。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1e5 + 5;
const int mod = 10007;
int node[maxn << 2];
int n, m, op, p;

void pushdown(int idx){
    if(node[idx]==-1) return;
    node[idx<<1] = node[idx<<1|1] = node[idx];
    node[idx] = -1;
}

void pushup(int idx){
    if(node[idx<<1] == node[idx<<1|1]) node[idx] = node[idx<<1];
}

void build(int idx, int l, int r){
    node[idx] = 0;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(idx<<1, l, mid);
    build(idx<<1|1, mid+1, r);
}

void update(int idx, int l, int r, int L, int R){
    if(L <= l && r <= R && node[idx] != -1){
        if(op == 1) node[idx] = (node[idx] + p) % mod;
        else if(op == 2) node[idx] = (node[idx] * p) % mod;
        else node[idx] = p;
        return;
    }
    pushdown(idx);
    int mid = (l + r) >> 1;
    if(L <= mid) update(idx<<1, l, mid, L, R);
    if(mid < R) update(idx<<1|1, mid+1, r, L, R);
    pushup(idx);
}

int query(int idx, int l, int r, int L, int R){
    if(L <= l && r <= R && node[idx] != -1){
        return (long long)pow(node[idx], p) * (r - l + 1) % mod;
    }
    pushdown(idx);
    int mid = (l + r) >> 1, res = 0;
    if(L <= mid) res = (res + query(idx<<1, l, mid, L, R)) % mod;
    if(mid < R) res = (res + query(idx<<1|1, mid+1, r, L, R)) % mod;
    return res;
}

int main(){
    while(~scanf("%d%d", &n, &m) && n){
        build(1, 1, n);
        for(int i = 0; i < m; i++){
            int x, y;
            scanf("%d%d%d%d", &op, &x, &y, &p);

            if(op < 4) update(1, 1, n, x, y);
            else printf("%d\n", query(1, 1, n, x, y));
        }
    }
    return 0;
}
View Code

 

HDU4614 Vases and Flowers

思路:二分查找。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 5e4 + 5;
int n, m;
int val[maxn<<2], w[maxn<<2];

void pushdown(int idx, int n){
    if(w[idx] != -1){
        w[idx<<1] = w[idx<<1|1] = w[idx];
        val[idx<<1] = (n - n/2) * w[idx];
        val[idx<<1|1] = n/2 * w[idx];
        w[idx] = -1;
    }
}

void build(int idx, int l, int r){
    if(l == r){
        val[idx] = 1, w[idx] = -1;
        return;
    }
    int mid = (l + r) >> 1;
    build(idx<<1, l, mid);
    build(idx<<1|1, mid+1, r);
    val[idx] = r - l + 1, w[idx] = -1;
}

void update(int idx, int l, int r, int L, int R, int v){
    if(L<=l && r<=R){
        w[idx] = v;
        val[idx] = (r - l + 1) * v;
        return;
    }
    pushdown(idx, r-l+1);
    int mid = (l + r) >> 1;
    if(L<=mid) update(idx<<1, l, mid, L, R, v);
    if(mid<R) update(idx<<1|1, mid+1, r, L, R, v);
    val[idx] = val[idx<<1] + val[idx<<1|1];
}

int query(int idx, int l, int r, int L, int R){
    if(L<=l && r<=R) return val[idx];
    pushdown(idx, r-l+1);
    int mid = (l + r) >> 1, res = 0;
    if(L<=mid) res += query(idx<<1, l, mid, L, R);
    if(mid<R) res += query(idx<<1|1, mid+1, r, L, R);
    return res;
}

int search(int st, int num){
    int l = st, r = n;
    int remain = query(1, 1, n, st, n);
    if(remain == 0) return -1;
    else if(remain < num){
        return search(st, remain);
    }
    while(l < r){
        int mid = (l + r) >> 1;
        int res = query(1, 1, n, st, mid);
        if(res >= num) r = mid;
        else if(res < num) l = mid+1;
    }
    return l;
}

void solve(int st, int num){
    int l = search(st, 1), r = search(st, num);
    if(r == -1) {
        printf("Can not put any one.\n");
        return;
    }
    printf("%d %d\n", l-1, r-1);
    update(1, 1, n, l, r, 0);
}

void print(int n){
    for(int i = 1; i <= n; i++)
        cout << query(1, 1, n, i, i) << ' ';
    cout << endl;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        build(1, 1, n);
        for(int i = 0; i < m; i++){
            int K, A, B;
            scanf("%d%d%d", &K, &A, &B);
            if(K == 1){
                solve(A+1, B);
            }
            else {
                printf("%d\n", (B-A+1) - query(1, 1, n, A+1, B+1));
                update(1, 1, n, A+1, B+1, 1);
            }
        }
        printf("\n");
    }
    return 0;
}
View Code

 

HDU4553 约会安排

 

POJ1177 Picture

 

posted @ 2021-02-22 09:52  Nanachi  阅读(78)  评论(0编辑  收藏  举报