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 ...
随机推荐
- 初识OpenCV-Python - 002: Drawing functions
使用OpenCV-Python 的画图函数画图. 本次的图形函数有: cv2.line(), cv2.circle(), cv2.rectangle(), cv2.ellipse(), cv2.put ...
- 【LGP5350】序列
题目 可能\(\operatorname{fhq\ treap}\)能做,但是珂朵莉树显然更好写 珂朵莉树是个很玄学的东西啊,就是直接使用\(\operatorname{std::set}\)维护每一 ...
- 如何在asp.net(C#)里用正则表达式验证手机号码
- PCA降维2
前言 本文为模式识别系列第一篇,主要介绍主成分分析算法(Principal Component Analysis,PCA)的理论,并附上相关代码.全文主要分六个部分展开: 1)简单示例.通过简单的例子 ...
- eclipse中启动tomcat之后,项目一直重复部署导致内存报警!!!
项目环境:jdk1.8+tomcat8.0; 出现该问题的原因:目前还没有确定,网友有很多的说法. 但是我在部署其中一个项目时出现此情况,在同样的环境下部署另外一个项目未出现此情况. 其中的一种解决方 ...
- Loadrunner安装与破解【转】
Loadrunner安装与破解 一.下载 我的LoadRunner 11下载地址是: http://pan.baidu.com/s/1qYFy2DI 二.安装 1.启动安装程序 运行setup.exe ...
- C++函数模板&类模板
函数模板 模板概念及语法 主要目的,简化代码,减少重复代码.基本语法格式: template<class T> 或者 template<typename T> //末尾不加分 ...
- 移动端自定义键盘的vue组件 ----keyboard
<style scoped lang="less"> .keyboard { /* height: 250px; */ width: 100%; position: f ...
- Java-MyBatis-MyBatis3-XML映射文件:缓存
ylbtech-Java-MyBatis-MyBatis3-XML映射文件:缓存 1.返回顶部 1. 缓存 MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制. 为了使它更 ...
- System.Web.Mvc.JsonResult.cs
ylbtech-System.Web.Mvc.JsonResult.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicK ...