zoukankan      html  css  js  c++  java
  • hdu 4638 Group 线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=4638

    线段树 离线处理

    题意为询问一段区间里的数能组成多少段连续的数。先考虑从左往右一个数一个数添加,考虑当前添加了i - 1个数的答案是x,那么添加完i个数后的答案是多少?可以看出,是根据a[i]-1a[i]+1是否已经添加而定的,如果a[i]-1或者a[i]+1已经添加一个,则段数不变,如果都没添加则段数加1,如果都添加了则段数减1。设v[i]为加入第i个数后的改变量,那么加到第x数时的段数就是sum{v[i]} (1<=i<=x}。仔细想想,若删除某个数,那么这个数两端的数的改变量也会跟着改变,这样一段区间的数构成的段数就还是他们的v值的和。将询问离线处理,按左端点排序后扫描一遍,左边删除,右边插入,查询就是求区间和。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define ls (rt<<1)
    #define rs ((rt<<1)|1)
    #define mid ((t[rt].l+t[rt].r)>>1)
    const int maxn = 101000;
    struct node {
        int l , r , sum;
    }t[maxn<<2];
    void pushup(int rt) {
        t[rt].sum = t[ls].sum + t[rs].sum;
    }
    void build(int l,int r,int rt) {
        t[rt].sum = 0; t[rt].l = l; t[rt].r = r;
        if(l == r) return;
        build(l,mid,ls);
        build(mid+1,r,rs);
    }
    void update(int pos , int val , int rt) {
        if(t[rt].l == t[rt].r) {
            t[rt].sum = val;
            return;
        }
        if(pos <= mid) update(pos , val , ls);
        else update(pos , val , rs);
        pushup(rt);
    }
    int query(int l ,int r,int rt) {
        if(t[rt].l == l && t[rt].r == r) return t[rt].sum;
        if(l > mid) return query(l, r, rs);
        else if(r <= mid) return query(l , r , ls);
        else return query(l , mid , ls) + query(mid+1 , r , rs);
    }
    int n , m , T;
    struct cmd {
        int l , r , id , ans;
    }c[maxn];
    bool cmp(cmd a , cmd b) {
        return a.l < b.l;
    }
    bool cmp2(cmd a , cmd b) {
        return a.id < b.id;
    }
    int a[maxn] , pos[maxn];
    int check(int num , int L) {
        int ans = 0;
        if(num > 1 && pos[num-1] >= L && pos[num-1] < pos[num] ) ans ++;
        if(num < n && pos[num+1] >= L && pos[num+1] < pos[num] ) ans ++;
        if(ans == 1) return 0;
        else if(ans == 2) return -1;
        else return 1;
    }
    int main() {
        scanf("%d" , &T);
        while(T--) {
            scanf("%d%d" ,&n , &m);
            build(1 , n , 1);
            for(int i=1;i<=n;i++) {
                scanf("%d" , &a[i]);
                pos[ a[i] ] = i;
            }
            for(int i=0;i<m;i++) {
                scanf("%d%d" , &c[i].l , &c[i].r);
                c[i].id = i;
            }
    
            sort(c , c + m , cmp);
            for(int i=1;i<=n;i++) {
                int val = check(a[i] , 0);
                update(i , val , 1);
            }
            int le = 0;
            for(int i=0;i<m;i++) {
                for(;le<c[i].l;le++) {
                    int val;
                    if(a[le] < n) {
                        val = check(a[le]+1 , c[i].l);
                        update(pos[ a[le]+1 ],val,1);
                    }
                    if(a[le] > 1) {
                        val = check(a[le]-1 , c[i].l);
                        update(pos[ a[le]-1 ],val,1);
                    }
                }
                c[i].ans = query(c[i].l , c[i].r , 1);
            }
            sort(c , c+m , cmp2);
            for(int i=0;i<m;i++) printf("%d
    " , c[i].ans);
        }
        return 0;
    }
    

     

      

     

  • 相关阅读:
    winphone 开发学习笔记(1)
    Performance testing of web application
    每天几步一点点
    其实做测试也不是想象中的简单
    【2019杭州集训12.09】向量
    【2019杭州集训】12.09训练总结
    【2019杭州集训】12.08训练总结
    burnside定理学习小计
    【CSP-S2019D2T3】树的重心
    【CSP-S2019D1T3】树上的数
  • 原文地址:https://www.cnblogs.com/tobec/p/3232437.html
Copyright © 2011-2022 走看看