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
原文地址:https://www.cnblogs.com/chaoswr/p/8948263.html