kuangbin带我飞QAQ 线段树
1. HDU1166
裸线段树点修改
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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:\n", 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\n", query(x,w,1,N,1) ); 110 } 111 } 112 return 0; 113 }
2.HDU 1754
不知道为什么scanf读不了char,变成了“烫烫烫烫”....还是裸线段树求区间最大
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", query(x, y, 1, N, 1) ); 107 } 108 } 109 return 0; 110 }
3.POJ 3468
简单的区间修改,但是容易错,数字全部都用long long 才行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", query(lhs, rhs, 1, N, 1)); } 118 } 119 120 return 0; 121 }
4.POJ 2528
区间染色+离散化,好题建议多做一遍,有一个坑点在于离散化后范围,你以为一共1e4对数据,所以最多2e4个点,实际上我们离散的时候如果两个区间之间相隔大于1,离散的时候是会加一个数字的,所以极限情况每对区间之间都加了一个点,所以得有3e4
个点,所以线段树数组至少得开4*3e4 = 12e4才行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", ans ); 145 } 146 return 0; 147 }
5. HDU 1698
区间修改,和上一题差不多,不过我觉得顺序出反了...明显这题简单嘛
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.\n", cnt++, ans ); 103 } 104 return 0; 105 }
6. POJ 3264
水题,求区间最大减最小
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", findmax(l,r,1,N,1) - findmin(l,r,1,N,1) ); 96 } 97 98 return 0; 99 }
7.HDU 1540
区间合并
求某个点左右两边的最长连续长度
恶心的题目,明明是多组数据写的却只有一组,各种WA的我又去看了kuangbin的代码结果又被误导了,,,看的我一愣一愣的最后发现还是自己写的好使...太坑了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n" ); 139 else 140 printf( "%d\n", query(x,1,n,1) ); 141 } 142 } 143 } 144 return 0; 145 }
8.HDU 3974
dfs建树,这是一道需要比较深入理解线段树操作的题目,WA了很多次是因为dfs的时候写成了start[i] = cnt++,这样如果到了叶子节点,那么start[i] 和end[i]就不等了,,,坑爹的是这种错误样例根本测不出来...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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:\n", 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\n", 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 }
9 HDU 4614
给N个瓶子,第一个操作,从第A个瓶子开始往里插x朵插花,如果一个瓶子里面没有花则放一朵花进去,如果有则找下一个直到最后一个瓶子,如果花没用完则舍弃掉,输出放第一朵花和最后一朵花的瓶子号
第二个操作,舍弃l~r区间内瓶子里的花,输出舍弃的花的数目
我是用数组1代表瓶子内无花,0代表有花,则区间和就代表没有花的瓶子个数,然后第一个操作就二分出起始瓶子和结尾瓶子,第二个操作直接区间长度-区间和
PS:十个二分九个错
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.\n"); 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\n", 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\n", len-tmp); 158 update( x+1, y+1, 1, 1, N, 1 ); 159 } 160 } 161 printf("\n"); 162 } 163 return 0; 164 }