kuangbin带我飞QAQ 线段树
1. HDU1166
裸线段树点修改
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const long long INF = 0x3f3f3f3f3f3f3f3f;
- const int inf = 0x3f3f3f3f;
- const int mod = ;
- const int maxk = 5e4+;
- const int maxn = 5e4+;
- int N;
- int num[maxn];
- int sum[maxn<<];
- char str[];
- void init()
- {
- memset( num, , sizeof(num) );
- memset( sum, , sizeof(sum) );
- }
- void pushup( int rt )
- { sum[rt] = sum[rt<<]+sum[rt<<|]; }
- void build( int l, int r, int rt )
- {
- if ( l == r )
- { sum[rt] = num[l]; return; }
- int m = (l+r)>>;
- build( l, m, rt<< );
- build( m+, r, rt<<| );
- pushup(rt);
- }
- void update(int L, int C, int l, int r, int rt)
- {
- if( l == r )
- { sum[rt]+=C; return; }
- int m=(l+r)>>;
- if(L <= m)
- update( L, C, l, m, rt<< );
- else
- update( L, C, m+, r, rt<<| );
- pushup(rt);
- }
- int query( int L, int R, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- return sum[rt];
- int m = (l+r)>>;
- int Ans = ;
- if ( L <= m ) Ans += query( L, R, l, m, rt<< );
- if ( R > m ) Ans += query( L, R, m+, r, rt<<| );
- return Ans;
- }
- int main()
- {
- int T; cin >> T;
- int cnt = ;
- while (T--)
- {
- init();
- scanf("%d", &N);
- for ( int i = ; i <= N; i++ )
- scanf( "%d", &num[i] );
- build( , N, );
- printf( "Case %d:\n", cnt++ );
- int x, w;
- while ()
- {
- scanf( "%s", str );
- if ( str[] == 'E' )
- break;
- scanf( "%d %d", &x, &w );
- if ( str[] == 'A' )
- update( x, w, , N, );
- else if ( str[] == 'S' )
- update( x, -w, , N, );
- else if ( str[] == 'Q' )
- printf( "%d\n", query(x,w,,N,) );
- }
- }
- return ;
- }
2.HDU 1754
不知道为什么scanf读不了char,变成了“烫烫烫烫”....还是裸线段树求区间最大
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const long long INF = 0x3f3f3f3f3f3f3f3f;
- const int inf = 0x3f3f3f3f;
- const int mod = ;
- const int maxk = 5e4+;
- const int maxn = 2e5+;
- int N;
- int num[maxn];
- int mmax[maxn<<];
- void pushup( int rt )
- { mmax[rt] = Max( mmax[rt<<], mmax[rt<<|] ); }
- void build( int l, int r, int rt )
- {
- if ( l == r )
- {
- mmax[rt] = num[l];
- return;
- }
- int m = (l+r)>>;
- build( l, m, rt<< );
- build( m+, r, rt<<| );
- pushup(rt);
- }
- void update( int L, int C, int l, int r, int rt )
- {
- if ( r == l )
- {
- mmax[rt] = C;
- return;
- }
- int mid = (l+r)>>;
- if ( L <= mid ) update( L, C, l, mid, rt<< );
- else update( L, C, mid+, r, rt<<| );
- pushup(rt);
- }
- int query( int lhs, int rhs, int l, int r, int rt )
- {
- if ( lhs <= l && rhs >= r )
- return mmax[rt];
- int mid = (l+r)>>;
- int m = -;
- if ( lhs <= mid ) m = Max( m, query(lhs, rhs, l, mid, rt<<) );
- if ( rhs > mid ) m = Max( m, query(lhs, rhs, mid+, r, rt<<|) );
- return m;
- }
- int main()
- {
- int N, M;
- char c[];
- char ch;
- while ( ~scanf("%d %d", &N, &M) )
- {
- memset( mmax, , sizeof(mmax) );
- for ( int i = ; i <= N; i++ )
- scanf("%d", &num[i]);
- build( , N, );
- int x, y;
- for ( int i = ; i <= M; i++ )
- {
- scanf("%s%d%d", &c, &x, &y);
- if ( c[] == 'U' )
- update( x, y, , N, );
- else
- printf( "%d\n", query(x, y, , N, ) );
- }
- }
- return ;
- }
3.POJ 3468
简单的区间修改,但是容易错,数字全部都用long long 才行
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const long long INF = 0x3f3f3f3f3f3f3f3f;
- const int inf = 0x3f3f3f3f;
- const int mod = ;
- const int maxk = 5e4+;
- const int maxn = 1e5+;
- int N;
- LL num[maxn], Add[maxn<<];
- LL sum[maxn<<];
- void pushup(LL rt) { sum[rt]=sum[rt<<]+sum[rt<<|]; }
- //ln是左子树数字节点的数目, rn是右子树数字节点的数目
- void pushdown( LL rt, LL ln, LL rn )
- {
- if ( Add[rt] != )
- {
- //下推标记
- Add[rt<<] += Add[rt];
- Add[rt<<|] += Add[rt];
- //修改子节点的sum
- sum[rt<<] += Add[rt]*ln;
- sum[rt<<|] += Add[rt]*rn;
- Add[rt] = ;
- }
- }
- void build( LL l, LL r, LL rt )
- {
- if ( l == r )
- {
- sum[rt] = num[l];
- return;
- }
- LL mid = (l+r)>>;
- build(l, mid, rt<<);
- build(mid+, r, rt<<|);
- pushup(rt);
- }
- void update( LL lhs, LL rhs, LL C,LL l, LL r, LL rt )
- {
- if ( lhs <= l && rhs >= r )
- {
- sum[rt] += (LL)C*(r-l+);
- Add[rt] += C;
- return;
- }
- LL mid = (l+r)>>;
- pushdown( rt, mid-l+, r-mid );
- if ( lhs <= mid ) update( lhs, rhs, C, l, mid, rt<< );
- if ( rhs > mid ) update( lhs, rhs, C, mid+, r, rt<<| );
- pushup(rt);
- }
- LL query( int lhs, LL rhs, LL l, LL r, LL rt )
- {
- if ( lhs <= l && rhs >= r )
- return sum[rt];
- LL mid = (l+r)>>;
- pushdown( rt, mid-l+, r-mid );
- LL ans = ;
- if ( lhs <= mid ) ans += query( lhs, rhs, l, mid, rt<< );
- if ( rhs > mid ) ans += query( lhs, rhs, mid+, r, rt<<| );
- return ans;
- }
- int main()
- {
- int N, Q;
- char str[];
- cin >> N >> Q;
- for ( int i = ; i <= N; i++ )
- scanf("%lld", &num[i]);
- build( , N, );
- LL lhs, rhs, x;
- while (Q--)
- {
- scanf( "%s", str );
- if ( str[] == 'C' )
- { scanf("%lld %lld %lld", &lhs, &rhs, &x); update(lhs, rhs, x, , N, ); }
- else
- { scanf("%lld %lld", &lhs, &rhs); printf("%lld\n", query(lhs, rhs, , N, )); }
- }
- return ;
- }
4.POJ 2528
区间染色+离散化,好题建议多做一遍,有一个坑点在于离散化后范围,你以为一共1e4对数据,所以最多2e4个点,实际上我们离散的时候如果两个区间之间相隔大于1,离散的时候是会加一个数字的,所以极限情况每对区间之间都加了一个点,所以得有3e4
个点,所以线段树数组至少得开4*3e4 = 12e4才行
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const long long INF = 0x3f3f3f3f3f3f3f3f;
- const int inf = 0x3f3f3f3f;
- const int mod = ;
- const int maxk = 1e4+;
- const int maxn = 1e6+;
- int N, ans;
- int num[maxk<<], lisan[maxk<<];
- int tree[maxk<<];
- int li[maxk], ri[maxk];
- bool has[maxk];
- //因为是染色问题所以没有上推
- void pushdown( int rt )
- {
- tree[rt<<] = tree[rt<<|] = tree[rt];
- tree[rt] = -;
- }
- void update( int L, int R, int C, int l, int r, int rt )
- {
- //因为范围已经覆盖了子树,所以直接修改标记也没关系
- if ( L <= l && R >= r )
- {
- tree[rt] = C;
- return;
- }
- //如果有标记,必须先下推标记才能修改tree
- if ( tree[rt] != - ) pushdown(rt);
- int mid = (l+r)>>;
- if ( L <= mid ) update( L, R, C, l, mid, rt<< );
- if ( R > mid ) update( L, R, C, mid+, r, rt<<| );
- //不用上推
- }
- int binary( int x, int l, int r )
- {
- while ( l < r )
- {
- int mid = (l+r)>>;
- if ( lisan[mid] == x )
- return mid;
- if ( lisan[mid] > x )
- r = mid - ;
- else
- l = mid + ;
- }
- return l;
- }
- void query( int l, int r, int rt )
- {
- if ( tree[rt] != - )
- {
- if ( !has[tree[rt]] )
- {
- ans++;
- has[tree[rt]] = true;
- }
- return;
- }
- //如果叶子节点有海报则在上一步肯定已经被计算过了,所以直接返回就行
- if ( l == r ) return;
- int mid = (l+r)>>;
- query( l, mid, rt<< );
- query( mid+, r, rt<<| );
- }
- int main()
- {
- int N;
- int T; cin >> T;
- while (T--)
- {
- scanf( "%d", &N );
- memset( tree, -, sizeof(tree) );
- int cnt = ;
- for ( int i = ; i <= N; i++ )
- {
- scanf( "%d %d", &li[i], &ri[i] );
- num[cnt++] = li[i];
- num[cnt++] = ri[i];
- }
- sort( num+, num+cnt );
- //int m = unique( num+1, num+cnt ) - num; //可以用这个去重
- int tmpcnt = cnt;
- for ( int i = ; i < cnt; i++ )
- {
- if (num[i] - num[i - ] > )
- num[tmpcnt++] = num[i - ]++;
- }
- sort( num+, num+tmpcnt );
- cnt = ;
- lisan[] = num[];
- for ( int i = ; i < tmpcnt; i++ )
- if ( num[i] != num[i-] )
- lisan[cnt++] = num[i];
- cnt--;
- for ( int i = ; i <= N; i++ )
- {
- int lhs = binary( li[i], , cnt );
- int rhs = binary( ri[i], , cnt );
- update( lhs, rhs, i, , cnt, );
- }
- ans = ;
- memset( has, , sizeof(has) );
- query( , cnt, );
- printf( "%d\n", ans );
- }
- return ;
- }
5. HDU 1698
区间修改,和上一题差不多,不过我觉得顺序出反了...明显这题简单嘛
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const long long INF = 0x3f3f3f3f3f3f3f3f;
- const int inf = 0x3f3f3f3f;
- const int mod = ;
- const int maxk = 1e5+;
- const int maxn = 1e5+;
- int ans;
- int tree[maxn<<];
- //void pushup( int rt ) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; }
- void pushdown( int rt )
- {
- tree[rt<<] = tree[rt<<|] = tree[rt];
- tree[rt] = -;
- }
- void update( int L, int R, int C, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- {
- tree[rt] = C;
- return;
- }
- if ( tree[rt] != - ) pushdown(rt);
- int mid = (l+r)>>;
- if ( L <= mid ) update( L, R, C, l, mid, rt<< );
- if ( R > mid ) update( L, R, C, mid+, r, rt<<| );
- //不用上推
- }
- void query( int l, int r, int rt )
- {
- //特判叶子节点
- if ( l == r )
- {
- if (tree[rt] == -) ans++;
- else
- ans += tree[rt];
- return;
- }
- if ( tree[rt]!=- )
- {
- ans += tree[rt]*(r-l+);
- return;
- }
- int mid = (l+r)>>;
- query(l, mid, rt<<);
- query(mid+, r, rt<<|);
- }
- int main()
- {
- int N, Q;
- int T, cnt = ; cin >> T;
- while (T--)
- {
- ans = ;
- memset( tree, -, sizeof(tree) );
- scanf( "%d", &N ); scanf( "%d", &Q );
- int lhs, rhs, z;
- for ( int i = ; i <= Q; i++ )
- {
- scanf( "%d %d %d", &lhs, &rhs, &z );
- update( lhs, rhs, z, , N, );
- }
- query( , N, );
- printf( "Case %d: The total value of the hook is %d.\n", cnt++, ans );
- }
- return ;
- }
6. POJ 3264
水题,求区间最大减最小
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 2e5+;
- int hei[maxn];
- int mmin[maxn<<], mmax[maxn<<];
- void pushup( int rt )
- {
- mmin[rt] = Min( mmin[rt<<], mmin[rt<<|] );
- mmax[rt] = Max( mmax[rt<<], mmax[rt<<|] );
- }
- void build( int l, int r, int rt )
- {
- if ( l == r )
- {
- mmin[rt] = hei[l];
- mmax[rt] = hei[l];
- return;
- }
- int mid = (l+r)>>;
- build( l, mid, rt<< );
- build( mid+, r, rt<<| );
- pushup(rt);
- }
- int findmin( int L, int R, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- return mmin[rt];
- int mid = (l+r)>>;
- int mi = inf;
- if ( L <= mid ) mi = Min( mi, findmin(L,R,l,mid,rt<<) );
- if ( R > mid ) mi = Min( mi, findmin(L,R,mid+,r,rt<<|) );
- return mi;
- }
- int findmax( int L, int R, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- return mmax[rt];
- int mid = (l+r)>>;
- int ma = -;
- if ( L <= mid ) ma = Max( ma, findmax(L,R,l,mid,rt<<) );
- if ( R > mid ) ma = Max( ma, findmax(L,R,mid+,r,rt<<|) );
- return ma;
- }
- int main()
- {
- int N, Q;
- cin >> N >> Q;
- for ( int i = ; i <= N; i++ )
- scanf( "%d", &hei[i] );
- build( , N, );
- int l, r;
- while (Q--)
- {
- scanf( "%d%d", &l, &r );
- printf("%d\n", findmax(l,r,,N,) - findmin(l,r,,N,) );
- }
- return ;
- }
7.HDU 1540
区间合并
求某个点左右两边的最长连续长度
恶心的题目,明明是多组数据写的却只有一组,各种WA的我又去看了kuangbin的代码结果又被误导了,,,看的我一愣一愣的最后发现还是自己写的好使...太坑了
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 5e4+;
- //rl代表从右到左最大连续村庄数,ll表示从左到右最大,ml表示该区间最大
- struct qujian {
- int l; //区间长度
- int ll, rl, ml;
- }qj[maxn<<];
- int sta[maxn], top;
- bool dead[maxn];
- void pushup( int rt )
- {
- int m = qj[lson].rl+qj[rson].ll;
- if (qj[lson].ml==qj[lson].l) qj[rt].ll = qj[lson].ll+qj[rson].ll;
- else qj[rt].ll = qj[lson].ll;
- if (qj[rson].ml==qj[rson].l) qj[rt].rl = qj[lson].rl+qj[rson].rl;
- else qj[rt].rl = qj[rson].rl;
- qj[rt].ml = Max( qj[rson].ml, qj[lson].ml );
- qj[rt].ml = Max( m, qj[rt].ml );
- }
- void build( int l, int r, int rt )
- {
- if ( l == r )
- {
- qj[rt].l = ;
- qj[rt].ll = ;
- qj[rt].ml = ;
- qj[rt].rl = ;
- return;
- }
- int mid = (l+r)>>;
- build( l, mid, rt<< );
- build( mid+, r, rt<<| );
- qj[rt].l = qj[lson].l + qj[rson].l;
- pushup(rt);
- }
- //删除是false, 恢复是true
- void update( int L, int l, int r, int rt, bool flag )
- {
- if ( l == r )
- {
- qj[rt].ll = qj[rt].rl = qj[rt].ml = flag?:;
- return;
- }
- int mid = (l+r)>>;
- if ( L <= mid ) update( L, l, mid, lson, flag );
- else update( L, mid+, r, rson, flag );
- pushup(rt);
- }
- int query( int L, int l, int r, int rt )
- {
- if ( l==r || qj[rt].ml==qj[rt].l || qj[rt].ml== )
- return qj[rt].ml;
- int mid = (l+r)>>;
- //如果在左子树,则lson的rl如果把查询点包括了,则要加上rson
- if ( L <= mid )
- {
- if ( qj[lson].rl- >= mid-L )
- return qj[lson].rl + qj[rson].ll;
- return query( L, l, mid, lson );
- }
- else //同上
- {
- if ( qj[rson].ll- >= L-mid- )
- return qj[rson].ll + qj[lson].rl;
- return query( L, mid+, r, rson );
- }
- }
- int main()
- {
- int n, m;
- while ( ~scanf("%d%d", &n, &m) )
- {
- top = ;
- memset( dead, , sizeof(dead) );
- build(,n,);
- char str[];
- int x;
- while (m--)
- {
- scanf( "%s", str );
- if ( str[] == 'D' )
- {
- scanf("%d",&x);
- sta[top++] = x;
- if (!dead[x])
- update( x, , n, , false );
- }
- else if (str[] == 'R')
- {
- if ( top )
- update(sta[--top], , n, , true);
- }
- else
- {
- scanf("%d",&x);
- if (dead[x]) printf( "0\n" );
- else
- printf( "%d\n", query(x,,n,) );
- }
- }
- }
- return ;
- }
8.HDU 3974
dfs建树,这是一道需要比较深入理解线段树操作的题目,WA了很多次是因为dfs的时候写成了start[i] = cnt++,这样如果到了叶子节点,那么start[i] 和end[i]就不等了,,,坑爹的是这种错误样例根本测不出来...
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 5e4+;
- struct edge {
- int to, next;
- }e[maxn];
- int cnt;
- int st[maxn], ed[maxn];
- int linjie[maxn], tree[maxn<<], change[maxn<<];
- bool vis[maxn];
- void addedge( int u, int v )
- { e[cnt].to = v; e[cnt].next = linjie[u]; linjie[u] = cnt++; }
- void init()
- {
- cnt = ;
- memset( linjie, -, sizeof(linjie) );
- memset( vis, , sizeof(vis) );
- memset( tree, -, sizeof(tree) );
- memset( change, -, sizeof(change) );
- }
- //妙,妙啊!
- void dfs( int u )
- {
- st[u] = ++cnt;
- for ( int i = linjie[u]; i+; i = e[i].next )
- dfs(e[i].to);
- ed[u] = cnt;
- }
- void pushdown( int rt )
- {
- if ( change[rt] != - )
- {
- int tmp = change[rt];
- change[lson] = change[rson] = tmp;
- tree[lson] = tree[rson] = tmp;
- change[rt] = -;
- }
- }
- void update( int L, int R, int C, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- {
- tree[rt] = C;
- change[rt] = C;
- return;
- }
- int mid = (l+r)>>;
- pushdown(rt);
- if ( L <= mid ) update( L, R, C, l, mid, lson );
- if ( R > mid ) update( L, R, C, mid+, r, rson );
- }
- int query( int L, int l, int r, int rt )
- {
- if ( L == l && L == r ) // L <= l && L >= r
- return tree[rt];
- pushdown(rt);
- int tmp = -, mid = (l+r)>>;
- if ( L <= mid ) tmp = query( L, l, mid, lson );
- else tmp = query( L, mid+, r, rson );
- return tmp;
- }
- int main()
- {
- freopen("F:\\cpp\\vs\\test\\Debug\\test.txt","r",stdin);
- int T; cin >> T;
- int N, Q, tot = ;
- char str[];
- while (T--)
- {
- init();
- cin >> N;
- int x, y;
- for ( int i = ; i < N; i++ )
- {
- scanf( "%d %d", &x, &y );
- vis[x] = true;
- addedge( y, x ); //从y到x
- }
- cnt = ;
- for ( int i = ; i <= N; i++ )
- if ( !vis[i] )
- { dfs(i); break; }
- cin >> Q;
- printf("Case #%d:\n", tot++);
- for ( int i = ; i <= Q; i++ )
- {
- scanf( "%s", str );
- if ( str[] == 'C' )
- {
- scanf( "%d", &x );
- printf( "%d\n", query(st[x], , cnt, ) );
- }
- else
- {
- scanf( "%d %d", &x, &y );
- update( st[x], ed[x], y, , cnt, );
- }
- }
- }
- return ;
- }
9 HDU 4614
给N个瓶子,第一个操作,从第A个瓶子开始往里插x朵插花,如果一个瓶子里面没有花则放一朵花进去,如果有则找下一个直到最后一个瓶子,如果花没用完则舍弃掉,输出放第一朵花和最后一朵花的瓶子号
第二个操作,舍弃l~r区间内瓶子里的花,输出舍弃的花的数目
我是用数组1代表瓶子内无花,0代表有花,则区间和就代表没有花的瓶子个数,然后第一个操作就二分出起始瓶子和结尾瓶子,第二个操作直接区间长度-区间和
PS:十个二分九个错
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 5e4+;
- int sum[maxn<<];
- int chag[maxn<<];
- void init()
- {
- memset( sum, , sizeof(sum) );
- memset( chag, -, sizeof(chag) );
- }
- void pushup( int rt ) { sum[rt] = sum[lson] + sum[rson]; }
- void build( int l, int r, int rt )
- {
- if ( l == r )
- {
- sum[rt] = ;
- return;
- }
- int mid = (l+r)>>;
- build( l, mid, lson );
- build( mid+, r, rson );
- pushup(rt);
- }
- //注意这个下推,只有两种操作,一个全部置0,一个全部置1
- //置1代表这个瓶子是空的,置0表示有花
- void pushdown( int rt, int ln, int rn )
- {
- if ( chag[rt] != - )
- {
- chag[lson] = chag[rson] = chag[rt];
- sum[lson] = ln*chag[lson];
- sum[rson] = rn*chag[rson];
- chag[rt] = -;
- }
- }
- void update( int L, int R, int C, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- {
- sum[rt] = (r-l+)*C;
- chag[rt] = C;
- return;
- }
- int mid = (l+r)>>;
- pushdown( rt, mid-l+, r-mid );
- if ( L <= mid ) update( L, R, C, l, mid, lson );
- if ( R > mid ) update( L, R, C, mid+, r, rson );
- pushup(rt);
- }
- int query( int L, int R, int l, int r, int rt )
- {
- if ( L <= l && R >= r )
- return sum[rt];
- int mid = (l+r)>>;
- pushdown( rt, mid-l+, r-mid );
- int ans = ;
- if ( L <= mid ) ans += query( L, R, l, mid, lson );
- if ( R > mid ) ans += query( L, R, mid+, r, rson );
- return ans;
- }
- int bin( int st, int ed, int val, bool ok )
- {
- int mid, tmp;
- int lhs = st, rhs = ed;
- while ( lhs <= rhs )
- {
- mid = (lhs+rhs)>>;
- tmp = query( st, mid, , ed, );
- if ( (ok?(val <= tmp):(val < tmp)) )
- rhs = mid-;
- else
- lhs = mid+;
- }
- return lhs;
- }
- int main()
- {
- //freopen("F:\\cpp\\test.txt","r",stdin);
- int T; cin >> T;
- int N, Q, k, x, y;
- while (T--)
- {
- init();
- cin >> N >> Q;
- build(, N, );
- int lpos, rpos;
- while (Q--)
- {
- scanf("%d%d%d", &k, &x, &y);
- if ( k == )
- {
- //t代表空瓶数量
- int t = query(x + , N, , N, );
- if ( t == )
- {
- printf("Can not put any one.\n");
- continue;
- }
- else if ( t < y ) //如果该段空花盆数目不够放
- rpos = bin( x+, N, t, true ); //找出第一个空瓶数量等于t的位置
- else
- rpos = bin( x+, N, y, true ); //如果够放直接二分终止位置
- //二分起始位置,查找第一个不等于0的数
- lpos = bin( x+, N, , false );
- printf( "%d %d\n", lpos-, rpos- ); //注意对齐位置
- update( lpos, rpos, , , N, );
- }
- else
- {
- int len = y-x+, tmp = query(x+, y+, , N, );
- printf("%d\n", len-tmp);
- update( x+, y+, , , N, );
- }
- }
- printf("\n");
- }
- return ;
- }
kuangbin带我飞QAQ 线段树的更多相关文章
- kuangbin带我飞QAQ 并查集
1. POJ 2236 给出N个点,一开始图是空白的,两个操作,一个是增加一个点(给出坐标),一个是查询两个点间是否相通,当两点间的距离小于D或者两点通过其他点间接相连时说这两个点相通.并查集维护,每 ...
- kuangbin带我飞QAQ DLX之一脸懵逼
1. hust 1017 DLX精确覆盖 模板题 勉强写了注释,但还是一脸懵逼,感觉插入方式明显有问题但又不知道哪里不对而且好像能得出正确结果真是奇了怪了 #include <iostream& ...
- kuangbin带我飞QAQ 最短路
1. poj 1502 Mathches Game 裸最短路 #include <iostream> #include <string.h> #include <cstd ...
- [kuangbin带你飞]专题七 线段树
ID Origin Title 228 / 440 Problem A HDU 1166 敌兵布阵 207 / 438 Problem B HDU 1754 I Hate It ...
- 【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵
https://vjudge.net/contest/66989#problem/A 单点修改,区间查询 方法一:线段树 http://www.cnblogs.com/kuangbin/archive ...
- 培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)
补坑咯~ 今天围绕的是一个神奇的数据结构:线段树.(感觉叫做区间树也挺科学的.) 线段树,顾名思义就是用来查找一段区间内的最大值,最小值,区间和等等元素. 那么这个线段树有什么优势呢? 比如我们要多次 ...
- Kuangbin 带你飞-线段树专题 题解
HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include < ...
- kuangbin专题七 HDU1540 Tunnel Warfare (前缀后缀线段树)
During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast a ...
- kuangbin专题七 POJ3264 Balanced Lineup (线段树最大最小)
For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One d ...
随机推荐
- 大半宿,封装了一个MP3播放器的类,写了个简陋的播放器
用 winmm.lib 写的 封装不是很好,而且没有优化,效率可能有问题,但是现在几乎没有什么大问题 我用我封装的类,写了一个小播放器,界面上的所有功能都实现了,包括双击列表中的文件名,直接播放文件 ...
- java笔试之求最大连续bit数
功能: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1 输入: 一个byte型的数字 输出: 无 返回: 对应的二进制数字中1 ...
- 【核心核心】10.Spring事务管理【TX】XML+注解方式
转账案例环境搭建 1.引入JAR包 IOC的6个包 AOP的4个包 C3P0的1个包 MySQL的1个驱动包 JDBC的2个目标包 整合JUnit测试1个包 2.引入配置文件 log4j.proper ...
- Android 开发 MediaRecorder视频录制入门
前言 MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另一篇博客里已经介绍.传送门: https://www.cnblogs.com/guanxinjing/p ...
- Oracle Database 18c数据库安装步骤
1.Oracle官网登录下载https://login.oracle.com/mysso/signon.jsp WINDOWS.X64_180000_db_home.zip 2.D盘根目录新建文件夹: ...
- 关于Synthesis
1,当追求面积最小时 会以牺牲Fmax为代价,可以使用一下setting: fit_pack_for_density=on fit_report_lab_usage_stats=on 可在 .qsf ...
- 12DUILib经典教程(实例)
Duilib经典实例教程:1基本框架:一个简单的Duilib程序一般是下面这个样子的:://Duilib使用设置部分:#pragmaonce:#defineWIN32_LEAN_AND_ME:#def ...
- 【BZOJ 1257】[CQOI2007]余数之和sum
一道LLJ说他吃*的题. 我实在是太愚蠢了. 传送门
- golang的表格驱动测试
一.leetcode的算法题 package main import ( "fmt" "strings" ) func lengthOfNonRepeating ...
- php中Sessions
PHP Sessions Session 中文译名叫做“会话”,其本来的含义是指有始有终的一系列动作/消息. PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会 ...