zoukankan      html  css  js  c++  java
  • kuangbin带我飞QAQ 线段树

      1. HDU1166

      裸线段树点修改

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #pragma warning ( disable : 4996 )
     14 
     15 using namespace std;
     16 typedef long long LL;
     17 
     18 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     19 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     20 inline int Max(int a,int b) { return a>b?a:b; }
     21 inline int Min(int a,int b) { return a>b?b:a; }
     22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     24 const long long INF = 0x3f3f3f3f3f3f3f3f;
     25 const int inf  = 0x3f3f3f3f;
     26 const int mod  = 7;
     27 const int maxk = 5e4+5;
     28 const int maxn = 5e4+5;
     29 
     30 int N;
     31 int num[maxn];
     32 int sum[maxn<<2];
     33 char str[10];
     34 
     35 void init()
     36 {
     37     memset( num, 0, sizeof(num) );
     38     memset( sum, 0, sizeof(sum) );
     39 }
     40 
     41 void pushup( int rt )
     42 { sum[rt] = sum[rt<<1]+sum[rt<<1|1]; }
     43 
     44 void build( int l, int r, int rt )
     45 {
     46     if ( l == r )
     47         { sum[rt] = num[l]; return; }
     48     int m = (l+r)>>1;
     49 
     50     build( l, m, rt<<1 );
     51     build( m+1, r, rt<<1|1 );
     52     pushup(rt);
     53 }
     54 
     55 void update(int L, int C, int l, int r, int rt)
     56 { 
     57     if( l == r )
     58         { sum[rt]+=C; return; }  
     59 
     60     int m=(l+r)>>1;   
     61 
     62     if(L <= m) 
     63         update( L, C, l, m, rt<<1 );  
     64     else       
     65         update( L, C, m+1, r, rt<<1|1 );  
     66     pushup(rt);
     67 }   
     68 
     69 int query( int L, int R, int l, int r, int rt )
     70 {
     71     if ( L <= l && R >= r )
     72         return sum[rt];
     73     
     74     int m = (l+r)>>1;
     75 
     76     int Ans = 0;
     77     if ( L <= m ) Ans += query( L, R, l, m, rt<<1 );
     78     if ( R > m ) Ans += query( L, R, m+1, r, rt<<1|1 );
     79     return Ans;
     80 }
     81 
     82 int main()
     83 {
     84     int T; cin >> T;
     85     int cnt = 1;
     86     while (T--)
     87     {
     88         init();
     89         scanf("%d", &N);
     90         for ( int i = 1; i <= N; i++ )
     91             scanf( "%d", &num[i] );
     92 
     93         build( 1, N, 1 );
     94         printf( "Case %d:
    ", cnt++ );
     95 
     96         int x, w;
     97         while (1)
     98         {
     99             scanf( "%s", str );
    100             if ( str[0] == 'E' )
    101                 break;
    102 
    103             scanf( "%d %d", &x, &w );
    104             if ( str[0] == 'A' )
    105                 update( x, w, 1, N, 1 );
    106             else if ( str[0] == 'S' )
    107                 update( x, -w, 1, N, 1 );
    108             else if ( str[0] == 'Q' )
    109                 printf( "%d
    ", query(x,w,1,N,1) );
    110         }
    111     }
    112     return 0;
    113 }
    View Code

       2.HDU 1754

      不知道为什么scanf读不了char,变成了“烫烫烫烫”....还是裸线段树求区间最大

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #pragma warning ( disable : 4996 )
     14 
     15 using namespace std;
     16 typedef long long LL;
     17 
     18 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     19 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     20 inline int Max(int a,int b) { return a>b?a:b; }
     21 inline int Min(int a,int b) { return a>b?b:a; }
     22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     24 const long long INF = 0x3f3f3f3f3f3f3f3f;
     25 const int inf  = 0x3f3f3f3f;
     26 const int mod  = 7;
     27 const int maxk = 5e4+5;
     28 const int maxn = 2e5+5;
     29 
     30 int N;
     31 int num[maxn];
     32 int mmax[maxn<<2];
     33 
     34 void pushup( int rt )
     35 { mmax[rt] = Max( mmax[rt<<1], mmax[rt<<1|1] ); }
     36 
     37 void build( int l, int r, int rt )
     38 {
     39     if ( l == r )
     40     {
     41         mmax[rt] = num[l];
     42         return;
     43     }
     44 
     45     int m = (l+r)>>1;
     46     build( l, m, rt<<1 );
     47     build( m+1, r, rt<<1|1 );
     48 
     49     pushup(rt);
     50 }
     51 
     52 void update( int L, int C, int l, int r, int rt )
     53 {
     54     if ( r == l )
     55     {
     56         mmax[rt] = C;
     57         return;
     58     }
     59 
     60     int mid = (l+r)>>1;
     61     if ( L <= mid ) update( L, C, l, mid, rt<<1 );
     62     else update( L, C, mid+1, r, rt<<1|1 );
     63 
     64     pushup(rt);
     65 }
     66 
     67 int query( int lhs, int rhs, int l, int r, int rt )
     68 {
     69 
     70     if ( lhs <= l && rhs >= r )
     71         return mmax[rt];
     72 
     73     int mid = (l+r)>>1;
     74     int m = -1;
     75 
     76     if ( lhs <= mid ) m = Max( m, query(lhs, rhs, l, mid, rt<<1) );
     77     if ( rhs > mid ) m = Max( m, query(lhs, rhs, mid+1, r, rt<<1|1) ); 
     78 
     79     return m;
     80 }
     81 
     82 
     83 int main()
     84 {
     85     int N, M;
     86     char c[2];
     87     char ch;
     88 
     89     while ( ~scanf("%d %d", &N, &M) )
     90     {
     91         memset( mmax, 0, sizeof(mmax) );
     92 
     93         for ( int i = 1; i <= N; i++ )
     94             scanf("%d", &num[i]);
     95 
     96         build( 1, N, 1 );
     97 
     98         int x, y;
     99         for ( int i = 1; i <= M; i++ )
    100         {
    101             scanf("%s%d%d", &c, &x, &y);
    102 
    103             if ( c[0] == 'U' )
    104                 update( x, y, 1, N, 1 );
    105             else
    106                 printf( "%d
    ", query(x, y, 1, N, 1) ); 
    107         }
    108     }
    109     return 0;
    110 }
    View Code

       3.POJ 3468 

      简单的区间修改,但是容易错,数字全部都用long long 才行

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #pragma warning ( disable : 4996 )
     14 
     15 using namespace std;
     16 typedef long long LL;
     17 
     18 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     19 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     20 inline int Max(int a,int b) { return a>b?a:b; }
     21 inline int Min(int a,int b) { return a>b?b:a; }
     22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     24 const long long INF = 0x3f3f3f3f3f3f3f3f;
     25 const int inf  = 0x3f3f3f3f;
     26 const int mod  = 7;
     27 const int maxk = 5e4+5;
     28 const int maxn = 1e5+5;
     29 
     30 int N;
     31 LL num[maxn], Add[maxn<<2];
     32 LL sum[maxn<<2];
     33 
     34 void pushup(LL rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; }
     35 
     36 //ln是左子树数字节点的数目, rn是右子树数字节点的数目
     37 void pushdown( LL rt, LL ln, LL rn ) 
     38 {
     39     if ( Add[rt] != 0 )
     40     {
     41         //下推标记
     42         Add[rt<<1] += Add[rt];
     43         Add[rt<<1|1] += Add[rt];
     44         //修改子节点的sum
     45         sum[rt<<1] += Add[rt]*ln;
     46         sum[rt<<1|1] += Add[rt]*rn;
     47 
     48         Add[rt] = 0;
     49     }
     50 }
     51 
     52 void build( LL l, LL r, LL rt )
     53 {
     54     if ( l == r )
     55     {
     56         sum[rt] = num[l];
     57         return;
     58     }
     59 
     60     LL mid = (l+r)>>1;
     61     build(l, mid, rt<<1);
     62     build(mid+1, r, rt<<1|1);
     63 
     64     pushup(rt);
     65 }
     66 
     67 void update( LL lhs, LL rhs, LL C,LL l, LL r, LL rt )
     68 {
     69     if ( lhs <= l && rhs >= r )
     70     {
     71         sum[rt] += (LL)C*(r-l+1);
     72         Add[rt] += C;
     73         return;
     74     }
     75 
     76     LL mid = (l+r)>>1;
     77     pushdown( rt, mid-l+1, r-mid );
     78 
     79     if ( lhs <= mid ) update( lhs, rhs, C, l, mid, rt<<1 );
     80     if ( rhs > mid ) update( lhs, rhs, C, mid+1, r, rt<<1|1 );
     81     pushup(rt);
     82 }
     83 
     84 LL query( int lhs, LL rhs, LL l, LL r, LL rt )
     85 {
     86     if ( lhs <= l && rhs >= r )
     87         return sum[rt];
     88 
     89     LL mid = (l+r)>>1;
     90     pushdown( rt, mid-l+1, r-mid );
     91 
     92     LL ans = 0;
     93     if ( lhs <= mid ) ans += query( lhs, rhs, l, mid, rt<<1 );
     94     if ( rhs > mid ) ans += query( lhs, rhs, mid+1, r, rt<<1|1 );
     95 
     96     return ans;
     97 }
     98 
     99 int main()
    100 {
    101     int N, Q;
    102     char str[2];
    103     cin >> N >> Q;
    104 
    105     for ( int i = 1; i <= N; i++ )
    106         scanf("%lld", &num[i]);
    107 
    108     build( 1, N, 1 );
    109 
    110     LL lhs, rhs, x;
    111     while (Q--)
    112     {
    113         scanf( "%s", str );
    114         if ( str[0] == 'C' )
    115             { scanf("%lld %lld %lld", &lhs, &rhs, &x); update(lhs, rhs, x, 1, N, 1); }
    116         else
    117             { scanf("%lld %lld", &lhs, &rhs); printf("%lld
    ", query(lhs, rhs, 1, N, 1)); }
    118     }
    119 
    120     return 0;
    121 }
    View Code

       4.POJ 2528

      区间染色+离散化,好题建议多做一遍,有一个坑点在于离散化后范围,你以为一共1e4对数据,所以最多2e4个点,实际上我们离散的时候如果两个区间之间相隔大于1,离散的时候是会加一个数字的,所以极限情况每对区间之间都加了一个点,所以得有3e4

    个点,所以线段树数组至少得开4*3e4 = 12e4才行

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #pragma warning ( disable : 4996 )
     14 
     15 using namespace std;
     16 typedef long long LL;
     17 
     18 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     19 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     20 inline int Max(int a,int b) { return a>b?a:b; }
     21 inline int Min(int a,int b) { return a>b?b:a; }
     22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     24 const long long INF = 0x3f3f3f3f3f3f3f3f;
     25 const int inf  = 0x3f3f3f3f;
     26 const int mod  = 7;
     27 const int maxk = 1e4+5;
     28 const int maxn = 1e6+100;
     29 
     30 int N, ans;
     31 int num[maxk<<2], lisan[maxk<<2];
     32 int tree[maxk<<4];
     33 int li[maxk], ri[maxk];
     34 bool has[maxk];
     35 //因为是染色问题所以没有上推
     36 void pushdown( int rt )
     37 { 
     38     tree[rt<<1] = tree[rt<<1|1] = tree[rt];
     39     tree[rt] = -1;
     40 }
     41 
     42 void update( int L, int R, int C, int l, int r, int rt )
     43 {
     44     //因为范围已经覆盖了子树,所以直接修改标记也没关系
     45     if ( L <= l && R >= r )
     46     {
     47         tree[rt] = C;
     48         return;
     49     }
     50 
     51     //如果有标记,必须先下推标记才能修改tree
     52     if ( tree[rt] != -1 ) pushdown(rt);
     53     int mid = (l+r)>>1;
     54     if ( L <= mid ) update( L, R, C, l, mid, rt<<1 );
     55     if ( R > mid ) update( L, R, C, mid+1, r, rt<<1|1 );
     56     //不用上推
     57 }
     58 
     59 
     60 int binary( int x, int l, int r )
     61 {
     62     while ( l < r )
     63     {
     64         int mid = (l+r)>>1;
     65         
     66         if ( lisan[mid] == x )
     67             return mid;
     68         if ( lisan[mid] > x )
     69             r = mid - 1;
     70         else 
     71             l = mid + 1;
     72     }
     73     return l;
     74 }
     75 
     76 void query( int l, int r, int rt )
     77 {
     78     if ( tree[rt] != -1 )
     79     {
     80         if ( !has[tree[rt]] )
     81         {
     82             ans++;
     83             has[tree[rt]] = true;
     84         }
     85         return;
     86     }
     87 
     88     //如果叶子节点有海报则在上一步肯定已经被计算过了,所以直接返回就行
     89     if ( l == r ) return;
     90 
     91     int mid = (l+r)>>1;
     92     query( l, mid, rt<<1 );
     93     query( mid+1, r, rt<<1|1 );
     94 }
     95 
     96 int main()
     97 {
     98     int N;
     99     int T; cin >> T;
    100     while (T--)
    101     {
    102         scanf( "%d", &N );
    103         memset( tree, -1, sizeof(tree) );
    104 
    105         int cnt = 1;
    106         for ( int i = 1; i <= N; i++ )
    107         {
    108             scanf( "%d %d", &li[i], &ri[i] );
    109             num[cnt++] = li[i];
    110             num[cnt++] = ri[i];
    111         }
    112 
    113         sort( num+1, num+cnt );
    114         //int m = unique( num+1, num+cnt ) - num;    //可以用这个去重
    115 
    116         int tmpcnt = cnt;
    117         for ( int i = 2; i < cnt; i++ )
    118         {
    119             if (num[i] - num[i - 1] > 1)
    120                 num[tmpcnt++] = num[i - 1]++; 
    121         }
    122 
    123         sort( num+1, num+tmpcnt );
    124 
    125         cnt = 2;
    126         lisan[1] = num[1];
    127         for ( int i = 2; i < tmpcnt; i++ )
    128             if ( num[i] != num[i-1] )
    129                 lisan[cnt++] = num[i];
    130         cnt--;
    131 
    132         for ( int i = 1; i <= N; i++ )
    133         {
    134             int lhs = binary( li[i], 1, cnt );
    135             int rhs = binary( ri[i], 1, cnt );
    136 
    137             update( lhs, rhs, i, 1, cnt, 1 );
    138         }
    139 
    140         ans = 0;
    141         memset( has, 0, sizeof(has) );
    142         query( 1, cnt, 1 );
    143 
    144         printf( "%d
    ", ans );
    145     }
    146     return 0;
    147 }
    View Code

       5. HDU 1698

      区间修改,和上一题差不多,不过我觉得顺序出反了...明显这题简单嘛

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #pragma warning ( disable : 4996 )
     14 
     15 using namespace std;
     16 typedef long long LL;
     17 
     18 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     19 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     20 inline int Max(int a,int b) { return a>b?a:b; }
     21 inline int Min(int a,int b) { return a>b?b:a; }
     22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     24 const long long INF = 0x3f3f3f3f3f3f3f3f;
     25 const int inf  = 0x3f3f3f3f;
     26 const int mod  = 7;
     27 const int maxk = 1e5+5;
     28 const int maxn = 1e5+5;
     29 
     30 int ans;
     31 int tree[maxn<<2];
     32 
     33 //void pushup( int rt ) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; }
     34 
     35 void pushdown( int rt )
     36 {
     37     tree[rt<<1] = tree[rt<<1|1] = tree[rt];
     38     tree[rt] = -1;
     39 }
     40 
     41 void update( int L, int R, int C, int l, int r, int rt )
     42 {
     43     if ( L <= l && R >= r )
     44     {
     45         tree[rt] = C;
     46         return;
     47     }
     48 
     49     if ( tree[rt] != -1 ) pushdown(rt);
     50 
     51     int mid = (l+r)>>1;
     52     if ( L <= mid ) update( L, R, C, l, mid, rt<<1 );
     53     if ( R > mid ) update( L, R, C, mid+1, r, rt<<1|1 );
     54     //不用上推
     55 }
     56 
     57 void query( int l, int r, int rt )
     58 {
     59     //特判叶子节点
     60     if ( l == r )
     61     {
     62         if (tree[rt] == -1) ans++;
     63         else
     64             ans += tree[rt];
     65         return;
     66     }
     67 
     68     if ( tree[rt]!=-1 )
     69     {
     70         ans += tree[rt]*(r-l+1);
     71         return;
     72     }
     73 
     74 
     75     int mid = (l+r)>>1;
     76     query(l, mid, rt<<1);
     77     query(mid+1, r, rt<<1|1);
     78 }
     79 
     80 
     81 
     82 int main()
     83 {
     84     int N, Q;
     85     int    T, cnt = 1; cin >> T;
     86 
     87     while (T--)
     88     {
     89         ans = 0;
     90         memset( tree, -1, sizeof(tree) );
     91 
     92         scanf( "%d", &N ); scanf( "%d", &Q );
     93 
     94         int lhs, rhs, z;
     95         for ( int i = 1; i <= Q; i++ )
     96         {
     97             scanf( "%d %d %d", &lhs, &rhs, &z );
     98             update( lhs, rhs, z, 1, N, 1 );
     99         }
    100 
    101         query( 1, N, 1 );
    102         printf( "Case %d: The total value of the hook is %d.
    ", cnt++, ans );
    103     }
    104     return 0;
    105 }
    View Code

       6. POJ 3264

      水题,求区间最大减最小

     1 #include <iostream>
     2 #include <string.h>
     3 #include <cstdio>
     4 #include <queue>
     5 #include <map>
     6 #include <vector>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <math.h>
    11 
    12 #define SIGMA_SIZE 26
    13 #define lson rt<<1
    14 #define rson rt<<1|1
    15 #pragma warning ( disable : 4996 )
    16 
    17 using namespace std;
    18 typedef long long LL;
    19 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
    20 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
    21 inline int Max(int a,int b) { return a>b?a:b; }
    22 inline int Min(int a,int b) { return a>b?b:a; }
    23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
    24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
    25 const LL INF = 0x3f3f3f3f3f3f3f3f;
    26 const LL mod  = 1000000007;
    27 const int inf  = 0x3f3f3f3f;
    28 const int maxk = 1e5+5;
    29 const int maxn = 2e5+5;
    30 
    31 int hei[maxn];
    32 int mmin[maxn<<2], mmax[maxn<<2];
    33 
    34 void pushup( int rt ) 
    35 {
    36     mmin[rt] = Min( mmin[rt<<1], mmin[rt<<1|1] );
    37     mmax[rt] = Max( mmax[rt<<1], mmax[rt<<1|1] );
    38 }
    39 
    40 void build( int l, int r, int rt )
    41 {
    42     if ( l == r )
    43     {
    44         mmin[rt] = hei[l];
    45         mmax[rt] = hei[l];
    46         return;
    47     }
    48 
    49     int mid = (l+r)>>1;
    50     build( l, mid, rt<<1 );
    51     build( mid+1, r, rt<<1|1 );
    52     pushup(rt);
    53 }
    54 
    55 int findmin( int L, int R, int l, int r, int rt )
    56 {
    57     if ( L <= l && R >= r )
    58         return mmin[rt];
    59 
    60     int mid = (l+r)>>1;
    61     int mi = inf;
    62 
    63     if ( L <= mid ) mi = Min( mi, findmin(L,R,l,mid,rt<<1) );
    64     if ( R > mid ) mi = Min( mi, findmin(L,R,mid+1,r,rt<<1|1) ); 
    65     return mi;
    66 }
    67 
    68 int findmax( int L, int R, int l, int r, int rt )
    69 {
    70     if ( L <= l && R >= r )
    71         return mmax[rt];
    72 
    73     int mid = (l+r)>>1;
    74     int ma = -1;
    75 
    76     if ( L <= mid ) ma = Max( ma, findmax(L,R,l,mid,rt<<1) );
    77     if ( R > mid ) ma = Max( ma, findmax(L,R,mid+1,r,rt<<1|1) );
    78     return ma;
    79 }
    80 
    81 int main()
    82 {
    83     int N, Q;
    84     cin >> N >>    Q;
    85 
    86     for ( int i = 1; i <= N; i++ )
    87         scanf( "%d", &hei[i] );
    88 
    89     build( 1, N, 1 );
    90 
    91     int l, r;
    92     while (Q--)
    93     {
    94         scanf( "%d%d", &l, &r );
    95         printf("%d
    ", findmax(l,r,1,N,1) - findmin(l,r,1,N,1) );
    96     }
    97     
    98     return 0;
    99 }
    View Code

       7.HDU 1540

      区间合并

      求某个点左右两边的最长连续长度

      恶心的题目,明明是多组数据写的却只有一组,各种WA的我又去看了kuangbin的代码结果又被误导了,,,看的我一愣一愣的最后发现还是自己写的好使...太坑了

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #define lson rt<<1
     14 #define rson rt<<1|1
     15 #pragma warning ( disable : 4996 )
     16 
     17 using namespace std;
     18 typedef long long LL;
     19 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     20 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     21 inline int Max(int a,int b) { return a>b?a:b; }
     22 inline int Min(int a,int b) { return a>b?b:a; }
     23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     25 const LL INF = 0x3f3f3f3f3f3f3f3f;
     26 const LL mod  = 1000000007;
     27 const int inf  = 0x3f3f3f3f;
     28 const int maxk = 1e5+5;
     29 const int maxn = 5e4+5;
     30 
     31 //rl代表从右到左最大连续村庄数,ll表示从左到右最大,ml表示该区间最大
     32 struct qujian {
     33     int l;        //区间长度
     34     int ll, rl, ml;
     35 }qj[maxn<<2];
     36 int sta[maxn], top;
     37 bool dead[maxn];
     38 
     39 void pushup( int rt )
     40 {
     41     int m = qj[lson].rl+qj[rson].ll;
     42 
     43     if (qj[lson].ml==qj[lson].l) qj[rt].ll = qj[lson].ll+qj[rson].ll;
     44     else qj[rt].ll = qj[lson].ll;
     45     
     46     if (qj[rson].ml==qj[rson].l) qj[rt].rl = qj[lson].rl+qj[rson].rl;
     47     else qj[rt].rl = qj[rson].rl;
     48 
     49 
     50     qj[rt].ml = Max( qj[rson].ml, qj[lson].ml );
     51     qj[rt].ml = Max( m, qj[rt].ml );
     52 }
     53 
     54 void build( int l, int r, int rt )
     55 {
     56     if ( l == r )
     57     {
     58         qj[rt].l = 1;
     59         qj[rt].ll = 1;
     60         qj[rt].ml = 1;
     61         qj[rt].rl = 1;
     62         return;
     63     }
     64 
     65     int mid = (l+r)>>1;
     66     build( l, mid, rt<<1 );
     67     build( mid+1, r, rt<<1|1 );
     68     qj[rt].l = qj[lson].l + qj[rson].l;
     69     pushup(rt);
     70 }
     71 
     72 //删除是false, 恢复是true
     73 void update( int L, int l, int r, int rt, bool flag )
     74 {
     75     if ( l == r )
     76     {
     77         qj[rt].ll = qj[rt].rl = qj[rt].ml = flag?1:0;
     78         return;
     79     }
     80     
     81     int mid = (l+r)>>1;
     82     if ( L <= mid ) update( L, l, mid, lson, flag );
     83     else update( L, mid+1, r, rson, flag );
     84     pushup(rt);
     85 }
     86 
     87 int query( int L, int l, int r, int rt ) 
     88 {
     89     if ( l==r || qj[rt].ml==qj[rt].l || qj[rt].ml==0 )
     90         return qj[rt].ml;
     91 
     92     int mid = (l+r)>>1;
     93     //如果在左子树,则lson的rl如果把查询点包括了,则要加上rson
     94     if ( L <= mid )
     95     {
     96         if ( qj[lson].rl-1 >= mid-L )
     97             return qj[lson].rl + qj[rson].ll;
     98         return query( L, l, mid, lson );
     99     }
    100     else   //同上
    101     {
    102         if ( qj[rson].ll-1 >= L-mid-1 )
    103             return qj[rson].ll + qj[lson].rl;
    104         return query( L, mid+1, r, rson );
    105     }
    106 }
    107 
    108 
    109 int main()
    110 {
    111     int n, m;
    112     while ( ~scanf("%d%d", &n, &m) )
    113     {
    114         top = 0;
    115         memset( dead, 0, sizeof(dead) );
    116         build(1,n,1);
    117 
    118         char str[2];
    119         int x;
    120         while (m--)
    121         {
    122             scanf( "%s", str );
    123             if ( str[0] == 'D' )
    124             {
    125                 scanf("%d",&x);
    126                 sta[top++] = x;
    127                 if (!dead[x])
    128                     update( x, 1, n, 1, false );
    129             }
    130             else if (str[0] == 'R')
    131             {
    132                 if ( top )
    133                     update(sta[--top], 1, n, 1, true);
    134             }
    135             else
    136             {
    137                 scanf("%d",&x);
    138                 if  (dead[x]) printf( "0
    " );
    139                 else
    140                     printf( "%d
    ", query(x,1,n,1) );
    141             }
    142         }
    143     }
    144     return 0;
    145 }
    View Code

       8.HDU 3974 

      dfs建树,这是一道需要比较深入理解线段树操作的题目,WA了很多次是因为dfs的时候写成了start[i] = cnt++,这样如果到了叶子节点,那么start[i] 和end[i]就不等了,,,坑爹的是这种错误样例根本测不出来...

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #define lson rt<<1
     14 #define rson rt<<1|1
     15 #pragma warning ( disable : 4996 )
     16 
     17 using namespace std;
     18 typedef long long LL;
     19 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     20 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     21 inline int Max(int a,int b) { return a>b?a:b; }
     22 inline int Min(int a,int b) { return a>b?b:a; }
     23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     25 const LL INF = 0x3f3f3f3f3f3f3f3f;
     26 const LL mod  = 1000000007;
     27 const int inf  = 0x3f3f3f3f;
     28 const int maxk = 1e5+5;
     29 const int maxn = 5e4+5;
     30 
     31 
     32 struct edge {
     33     int to, next;
     34 }e[maxn];
     35 
     36 int cnt;
     37 int st[maxn], ed[maxn];
     38 int linjie[maxn], tree[maxn<<2], change[maxn<<2];
     39 bool vis[maxn];
     40 
     41 void addedge( int u, int v )
     42 { e[cnt].to = v; e[cnt].next = linjie[u]; linjie[u] = cnt++; }
     43 
     44 void init()
     45 {
     46     cnt = 0;
     47     memset( linjie, -1, sizeof(linjie) );
     48     memset( vis, 0, sizeof(vis) );
     49     memset( tree, -1, sizeof(tree) );
     50     memset( change, -1, sizeof(change) );
     51 }
     52 
     53 //妙,妙啊!
     54 void dfs( int u )
     55 {
     56     st[u] = ++cnt;
     57     for ( int i = linjie[u]; i+1; i = e[i].next )
     58         dfs(e[i].to);
     59     ed[u] = cnt;
     60 }
     61 
     62 void pushdown( int rt )
     63 {
     64     if ( change[rt] != -1 )
     65     {
     66         int tmp = change[rt];
     67         change[lson] = change[rson] = tmp;
     68         tree[lson] = tree[rson] = tmp;
     69 
     70         change[rt] = -1;
     71     }
     72 }
     73 
     74 void update( int L, int R, int C, int l, int r, int rt ) 
     75 {
     76     if ( L <= l && R >= r )
     77     {
     78         tree[rt] = C;
     79         change[rt] = C;
     80         return;
     81     }
     82 
     83     int mid = (l+r)>>1;
     84     pushdown(rt);
     85 
     86     if ( L <= mid ) update( L, R, C, l, mid, lson );
     87     if ( R > mid ) update( L, R, C, mid+1, r, rson );
     88 }
     89 
     90 int query( int L, int l, int r, int rt )
     91 {
     92     if ( L == l && L == r )  // L <= l && L >= r
     93         return tree[rt]; 
     94 
     95     pushdown(rt);
     96     int tmp = -1, mid = (l+r)>>1;
     97 
     98     if ( L <= mid ) tmp = query( L, l, mid, lson );
     99     else tmp = query( L, mid+1, r, rson );
    100 
    101     return tmp;
    102 }
    103 
    104 int main()
    105 {
    106     freopen("F:\cpp\vs\test\Debug\test.txt","r",stdin); 
    107 
    108     int T; cin >> T;
    109     
    110     int N, Q, tot = 1;
    111     char str[2];
    112 
    113     while (T--)
    114     {
    115         init();
    116         cin >> N;
    117         
    118         int x, y;
    119         for ( int i = 1; i < N; i++ )
    120         {
    121             scanf( "%d %d", &x, &y );
    122             vis[x] = true;
    123             addedge( y, x );        //从y到x
    124         }
    125 
    126         cnt = 0;
    127         for ( int i = 1; i <= N; i++ )
    128             if ( !vis[i] )
    129             { dfs(i); break; }
    130 
    131 
    132         cin >> Q;
    133         printf("Case #%d:
    ", tot++);
    134         for ( int i = 1; i <= Q; i++ )
    135         {
    136             scanf( "%s", str );
    137             if ( str[0] == 'C' )
    138             {
    139                 scanf( "%d", &x );
    140                 printf( "%d
    ", query(st[x], 1, cnt, 1) ); 
    141             }
    142             else
    143             {
    144                 scanf( "%d %d", &x, &y );
    145                 update( st[x], ed[x], y, 1, cnt, 1 );
    146             }
    147         }
    148 
    149     }
    150     return 0;
    151 }
    View Code

       9 HDU 4614

      给N个瓶子,第一个操作,从第A个瓶子开始往里插x朵插花,如果一个瓶子里面没有花则放一朵花进去,如果有则找下一个直到最后一个瓶子,如果花没用完则舍弃掉,输出放第一朵花和最后一朵花的瓶子号

    第二个操作,舍弃l~r区间内瓶子里的花,输出舍弃的花的数目

    我是用数组1代表瓶子内无花,0代表有花,则区间和就代表没有花的瓶子个数,然后第一个操作就二分出起始瓶子和结尾瓶子,第二个操作直接区间长度-区间和

    PS:十个二分九个错

      1 #include <iostream>
      2 #include <string.h>
      3 #include <cstdio>
      4 #include <queue>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <math.h>
     11 
     12 #define SIGMA_SIZE 26
     13 #define lson rt<<1
     14 #define rson rt<<1|1
     15 #pragma warning ( disable : 4996 )
     16 
     17 using namespace std;
     18 typedef long long LL;
     19 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
     20 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
     21 inline int Max(int a,int b) { return a>b?a:b; }
     22 inline int Min(int a,int b) { return a>b?b:a; }
     23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
     24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
     25 const LL INF = 0x3f3f3f3f3f3f3f3f;
     26 const LL mod  = 1000000007;
     27 const int inf  = 0x3f3f3f3f;
     28 const int maxk = 1e5+5;
     29 const int maxn = 5e4+5;
     30 
     31 int sum[maxn<<2];
     32 int chag[maxn<<2];
     33 
     34 void init()
     35 {
     36     memset( sum, 0, sizeof(sum) );
     37     memset( chag, -1, sizeof(chag) ); 
     38 }
     39 
     40 void pushup( int rt ) { sum[rt] = sum[lson] + sum[rson]; }
     41 
     42 void build( int l, int r, int rt )
     43 {
     44     if ( l == r )
     45     {
     46         sum[rt] = 1;
     47         return;
     48     }
     49 
     50     int mid = (l+r)>>1;
     51     build( l, mid, lson );
     52     build( mid+1, r, rson );
     53     pushup(rt);
     54 }
     55 
     56 //注意这个下推,只有两种操作,一个全部置0,一个全部置1
     57 //置1代表这个瓶子是空的,置0表示有花
     58 void pushdown( int rt, int ln, int rn )
     59 {
     60     if ( chag[rt] != -1 )
     61     {
     62         chag[lson] = chag[rson] = chag[rt];
     63         sum[lson] = ln*chag[lson];
     64         sum[rson] = rn*chag[rson];
     65         chag[rt] = -1;
     66     }
     67 }
     68 
     69 void update( int L, int R, int C, int l, int r, int rt )
     70 {
     71     if ( L <= l && R >= r )
     72     {
     73         sum[rt] = (r-l+1)*C;
     74         chag[rt] = C;
     75         return;
     76     }
     77 
     78     int mid = (l+r)>>1;
     79     pushdown( rt, mid-l+1, r-mid );
     80 
     81     if ( L <= mid ) update( L, R, C, l, mid, lson );
     82     if ( R > mid ) update( L, R, C, mid+1, r, rson );
     83     pushup(rt);
     84 }
     85 
     86 int query( int L, int R, int l, int r, int rt )
     87 {
     88     if ( L <= l && R >= r )
     89         return sum[rt];
     90 
     91     int mid = (l+r)>>1;
     92     pushdown( rt, mid-l+1, r-mid );
     93 
     94     int ans = 0;
     95     if ( L <= mid ) ans += query( L, R, l, mid, lson );
     96     if ( R > mid ) ans += query( L, R, mid+1, r, rson );
     97 
     98     return ans;
     99 }
    100 
    101 int bin( int st, int ed, int val, bool ok )
    102 {
    103     int mid, tmp;
    104     int lhs = st, rhs = ed;
    105     while ( lhs <= rhs )
    106     {
    107         mid = (lhs+rhs)>>1;
    108         tmp = query( st, mid, 1, ed, 1 );
    109         if ( (ok?(val <= tmp):(val < tmp)) )
    110             rhs = mid-1;
    111         else
    112             lhs = mid+1;
    113     }
    114     return lhs;
    115 }
    116 
    117 int main()
    118 {
    119     //freopen("F:\cpp\test.txt","r",stdin); 
    120 
    121     int T; cin >> T;
    122 
    123     int N, Q, k, x, y;
    124     while (T--)
    125     {
    126         init();
    127         cin >> N >> Q;
    128         build(1, N, 1);
    129 
    130         int lpos, rpos;
    131         while (Q--)
    132         {
    133             scanf("%d%d%d", &k, &x, &y);
    134             if ( k == 1 )
    135             {
    136                 //t代表空瓶数量
    137                 int t = query(x + 1, N, 1, N, 1);
    138                 if ( t == 0 )
    139                 {
    140                     printf("Can not put any one.
    ");
    141                     continue;
    142                 }
    143                 else if ( t < y )                        //如果该段空花盆数目不够放
    144                     rpos = bin( x+1, N, t, true );        //找出第一个空瓶数量等于t的位置
    145                 else
    146                     rpos = bin( x+1, N, y, true );        //如果够放直接二分终止位置
    147                 
    148                 //二分起始位置,查找第一个不等于0的数
    149                 lpos = bin( x+1, N, 0, false );
    150 
    151                 printf( "%d %d
    ", lpos-1, rpos-1 );            //注意对齐位置
    152                 update( lpos, rpos, 0, 1, N, 1 );
    153             }
    154             else
    155             {
    156                 int len = y-x+1, tmp = query(x+1, y+1, 1, N, 1);
    157                 printf("%d
    ", len-tmp);
    158                 update( x+1, y+1, 1, 1, N, 1 );
    159             }
    160         }
    161         printf("
    ");
    162     }
    163     return 0;
    164 }
    View Code
  • 相关阅读:
    UVA1401 Remember the word DP+Trie
    LG5202 「USACO2019JAN」Redistricting 动态规划+堆/单调队列优化
    模拟赛总结合集
    LG5201 「USACO2019JAN」Shortcut 最短路树
    LG5200 「USACO2019JAN」Sleepy Cow Sorting 树状数组
    LG5196 「USACO2019JAN」Cow Poetry 背包+乘法原理
    20190922 「HZOJ NOIP2019 Round #7」20190922模拟
    LG2530 「SHOI2001」化工厂装箱员 高维DP+记忆化搜索
    LG2893/POJ3666 「USACO2008FEB」Making the Grade 线性DP+决策集优化
    关于对QQ 输入法的评价
  • 原文地址:https://www.cnblogs.com/chaoswr/p/8948263.html
Copyright © 2011-2022 走看看