伸展树模板(BZOJ 1500,UVALive 3961 HDU 1890)
来源:互联网 发布:纯js 的时间控件 编辑:程序博客网 时间:2024/05/16 14:55
伸展树和名次树基本上差不多,直接上模板。
维修数列
链表实现
#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <cstdlib>#include <utility>#include <map>#include <set>#include <queue>#include <vector>#include <iostream>#include <stack>using namespace std;#define INF 0x3f3f3f3f#define eps 1e-6#define CLR( a, v ) memset ( a, v, sizeof ( a ) )#define LL long long#define DBUG printf ( "here!!!\n" )#define rep( i, a, b ) for ( int i = ( a ); i < ( b ); i ++ )#define PB push_back#define ULL unsigned long long#define PI acos ( -1.0 )#define lson l, m, rt << 1#define rson m+1, r, rt << 1 | 1#define lowbit( x ) ( ( x )&( -x ) )#define CASE int Test; scanf ( "%d", &Test ); for ( int cas = 1; cas <= Test; cas ++ )#define ALL( x ) x.begin ( ), x.end ( )#define INS( x ) x, x.begin ( )typedef pair < int, int > Pii;typedef pair < double, double > Pdd;typedef set < int > Set;const int maxn = 500005;int read_int ( ){ int res = 0; int ch; while ( ( ch = getchar ( ) ) && ! ( ch >= '0' && ch <= '9' ) ) { if ( ch == -1 ) return -1; } while ( ch >= '0' && ch <= '9' ) { res = res*10+( ch-'0' ); ch = getchar ( ); } return res;}struct Node{ int x, cnt, lv, mv, rv, rev; int md, sum; struct Node * ch[2]; void maintain ( ) { cnt = ch[0]->cnt+ch[1]->cnt+1; sum = ch[0]->sum+ch[1]->sum+x; //维护子串和 lv = max ( ch[0]->lv, ch[0]->sum+x+max ( 0, ch[1]->lv ) ); rv = max ( ch[1]->rv, ch[1]->sum+x+max ( 0, ch[0]->rv ) ); mv = max ( ch[0]->mv, ch[1]->mv ); mv = max ( mv, max ( 0, ch[0]->rv )+x+max ( 0, ch[1]->lv ) ); } void modify ( int s ) { md = s; x = s; lv = mv = rv = max ( s, cnt*s ); //s可能为负数 sum = cnt*s; } void reverse ( ) { swap ( ch[0], ch[1] ); swap ( lv, rv ); rev ^= 1; //注意只要当前rev更新 } void PushDown ( ) { if ( md != INF ) { rev = 0; if ( ch[0]->cnt ) ch[0]->modify ( md ); if ( ch[1]->cnt ) ch[1]->modify ( md ); md = INF; } if ( rev ) { rev = 0; if ( ch[0]->cnt ) ch[0]->reverse ( ); if ( ch[1]->cnt ) ch[1]->reverse ( ); } } int cmp ( int k ) { int d = k-ch[0]->cnt; if ( d == 1 ) return -1; return d <= 0 ? 0 : 1; }}*root, *null;int a[maxn], cc;Node * Build ( int L, int R ){ if ( L >= R ) return null; int M = ( L+R ) >> 1; Node * p = new Node ( ); p->x = p->lv = p->mv = p->rv = p->sum = a[M]; p->rev = 0; p->md = INF; p->ch[0] = Build ( L, M ); p->ch[1] = Build ( M+1, R ); p->maintain ( ); return p;}void Rotate ( Node * &o, int k ){ Node * p = o->ch[k^1]; o->ch[k^1] = p->ch[k]; p->ch[k] = o; o->maintain ( ); p->maintain ( ); o = p;}void splay ( Node * &o, int k ){ o->PushDown ( ); int d = o->cmp ( k ); if ( d == 1 ) k -= o->ch[0]->cnt+1; if ( d != -1 ) { Node * p = o->ch[d]; p->PushDown ( ); int d2 = p->cmp ( k ); int k2 = ( d2 == 0 ? k : k-p->ch[0]->cnt-1 ); if ( d2 != -1 ) { splay ( p->ch[d2], k2 ); if ( d == d2 ) Rotate ( o, d^1 ); else Rotate ( o->ch[d], d ); } Rotate ( o, d^1 ); } o->maintain ( );}void split ( Node * o, int k, Node * &left, Node * &right ){ splay ( o, k ); left = o; right = o->ch[1]; left->ch[1] = null; left->maintain ( );}Node * Merge ( Node * left, Node * right ){ splay ( left, left->cnt ); left->ch[1] = right; left->maintain ( ); return left;}void print ( Node * o ){ if ( o == null ) return ; o->PushDown ( ); print ( o->ch[0] ); printf ( "%d ", o->x ); print ( o->ch[1] );}void remove ( Node * &o ){ if ( o == null ) return ; remove ( o->ch[0] ); remove ( o->ch[1] ); delete o; o = null;}void solve ( ){ int n, m, pos, tot, x; char op[15]; null = new Node ( ); null->x = null->cnt = null->rev = null->sum = 0; null->lv = null->mv = null->rv = -INF; Node *o, *left, *mid, *right; //freopen ( "in0.in", "r", stdin ); //freopen ( "in1.out", "w", stdout ); scanf ( "%d%d", &n, &m ); cc = 0; for ( int i = 1; i <= n; i ++ ) scanf ( "%d", &a[i] ); root = Build ( 1, n+1 ); while ( m -- ) { scanf ( "%s", op ); if ( op[0] == 'I' ) { scanf ( "%d%d", &pos, &tot ); if ( tot == 0 ) continue ; for ( int i = 1; i <= tot; i ++ ) scanf ( "%d", &a[i] ); o = Build ( 1, tot+1 ); if ( pos == 0 ) root = Merge ( o, root ); else { split ( root, pos, left, right ); root = Merge ( Merge ( left, o ), right ); } } else if ( op[0] == 'D' ) { scanf ( "%d%d", &pos, &tot ); if ( tot == 0 ) continue ; if ( pos == 1 ) { split ( root, tot, left, o ); remove ( left ); root = o; } else { split ( root, pos-1, left, o ); split ( o, tot, mid, right ); remove ( mid ); root = Merge ( left, right ); } } else if ( op[0] == 'M' ) { if ( strcmp ( op, "MAKE-SAME" ) == 0 ) { scanf ( "%d%d%d", &pos, &tot, &x ); if ( tot == 0 ) continue ; if ( pos == 1 ) { split ( root, tot, left, o ); left->modify ( x ); root = Merge ( left, o ); } else { split ( root, pos-1, left, o ); split ( o, tot, mid, right ); mid->modify ( x ); root = Merge ( Merge ( left, mid ), right ); } } else printf ( "%d\n", root->mv ); } else if ( op[0] == 'R' ) { scanf ( "%d%d", &pos, &tot ); if ( pos == 1 ) { split ( root, tot, left, o ); left->reverse ( ); root = Merge ( left, o ); } else { split ( root, pos-1, left, o ); split ( o, tot, mid, right ); mid->reverse ( ); root = Merge ( Merge ( left, mid ), right ); } } else { scanf ( "%d%d", &pos, &tot ); if ( tot == 0 ) //tot为0处理 { printf ( "0\n" ); continue ; } if ( pos == 1 ) { split ( root, tot, left, o ); printf ( "%d\n", left->sum ); root = Merge ( left, o ); } else { split ( root, pos-1, left, o ); split ( o, tot, mid, right ); printf ( "%d\n", mid->sum ); root = Merge ( Merge ( left, mid ), right ); } } //print ( root ); //printf ( "\n" ); }}int main ( ){ solve ( ); return 0;}
UVaLive 3961 HDU 1890
这题主要是将某个点旋转至某个节点的操作,所以需要保存父节点。
数组实现
#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <cstdlib>#include <utility>#include <map>#include <set>#include <queue>#include <vector>#include <iostream>#include <stack>using namespace std;#define INF 0x3f3f3f3f#define eps 1e-6#define CLR( a, v ) memset ( a, v, sizeof ( a ) )#define LL long long#define DBUG printf ( "here!!!\n" )#define rep( i, a, b ) for ( int i = ( a ); i < ( b ); i ++ )#define PB push_back#define ULL unsigned long long#define PI acos ( -1.0 )#define lson l, m, rt << 1#define rson m+1, r, rt << 1 | 1#define lowbit( x ) ( ( x )&( -x ) )#define CASE int Test; scanf ( "%d", &Test ); for ( int cas = 1; cas <= Test; cas ++ )#define ALL( x ) x.begin ( ), x.end ( )#define INS( x ) x, x.begin ( )#define Key_value ch[ ch[root][1] ][0]typedef pair < int, int > Pii;typedef pair < double, double > Pdd;typedef set < int > Set;const int maxn = 100005;int read_int ( ){ int res = 0; int ch; while ( ( ch = getchar ( ) ) && ! ( ch >= '0' && ch <= '9' ) ) { if ( ch == -1 ) return -1; } while ( ch >= '0' && ch <= '9' ) { res = res*10+( ch-'0' ); ch = getchar ( ); } return res;}int ch[maxn][2], cnt[maxn], rev[maxn], pre[maxn];int tot, pp[maxn], root, key[maxn], mp[maxn];void newNode ( int &r, int fa, int k ){ r = ++ tot; pre[r] = fa; ch[r][0] = ch[r][1] = rev[r] = 0; key[r] = k;}void PushUP ( int x ){ cnt[x] = cnt[ ch[x][0] ]+cnt[ ch[x][1] ]+1;}void Rever ( int x ){ if ( x == 0 ) return ; swap ( ch[x][0], ch[x][1] ); rev[x] ^= 1;}void PushDown ( int x ){ if ( rev[x] ) { Rever ( ch[x][0] ); Rever ( ch[x][1] ); rev[x] = 0; }}void Build ( int &x, int L, int R, int fa ){ if ( L >= R ) { x = 0; return ; } int M = ( L+R ) >> 1; newNode ( x, fa, pp[M] ); mp[ pp[M] ] = x; Build ( ch[x][0], L, M, x ); Build ( ch[x][1], M+1, R, x ); PushUP ( x );}Pii a[maxn];int cmp ( Pii x, Pii y ){ return x.first < y.first || x.first == y.first && x.second < y.second;}void Init ( int n ){ root = tot = 0; for ( int i = 1; i <= n; i ++ ) { scanf ( "%d", &a[i].first ); a[i].second = i; } sort ( a+1, a+1+n, cmp ); for ( int i = 1; i <= n; i ++ ) pp[ a[i].second ] = i; ch[root][0] = ch[root][1] = cnt[root] = rev[root] = pre[root] = 0; newNode ( root, 0, -1 ); newNode ( ch[root][1], root, -1 ); Build ( Key_value, 1, n+1, ch[root][1] ); PushUP ( ch[root][1] ); PushUP ( root );}void Rotate ( int x, int k ){ int y = pre[x]; ch[y][k^1] = ch[x][k]; if ( ch[x][k] ) pre[ ch[x][k] ] = y; ch[x][k] = y; if ( pre[y] ) ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x; pre[x] = pre[y]; pre[y] = x; PushUP ( y ); PushUP ( x );}void Splay ( int x, int goal ){ PushDown ( x ); while ( pre[x] != goal ) { int y = pre[x]; PushDown ( y ); PushDown ( x ); if ( pre[y] == goal ) Rotate ( x, ch[y][0] == x ); else { int z = pre[y]; PushDown ( z ); PushDown ( y ); PushDown ( x ); int d = ch[z][1] == y, d2 = ch[y][1] == x; if ( d == d2 ) Rotate ( x, d^1 ); else Rotate ( x, d ); Rotate ( x, d^1 ); } } PushUP ( x ); if ( goal == 0 ) root = x;}int Get_Kth ( int x, int k ){ PushDown ( x ); //注意需要向下更新否则中间运行会有问题 int d = cnt[ ch[x][0] ]+1; if ( d == k ) return x; if ( d > k ) return Get_Kth ( ch[x][0], k ); return Get_Kth ( ch[x][1], k-d );}void solve ( ){ int n; //freopen ( "in0.in", "r", stdin ); while ( ~ scanf ( "%d", &n ), n ) { Init ( n ); for ( int i = 1; i <= n; i ++ ) { Splay ( mp[i], root ); printf ( i == 1 ? "%d" : " %d", i+cnt[Key_value] ); Rever ( Key_value ); Splay ( Get_Kth( ch[root][1], cnt[Key_value]+2 ), root ); Splay ( Get_Kth ( Key_value, cnt[Key_value] ), ch[root][1] ); int x = ch[Key_value][0]; if ( x ) pre[x] = ch[root][1]; Key_value = x; PushUP ( ch[root][1] ); PushUP ( root ); } printf ( "\n" ); }}int main ( ){ solve ( ); return 0;}
0 0
- 伸展树模板(BZOJ 1500,UVALive 3961 HDU 1890)
- HDU 3487(伸展树模板)
- bzoj 1014伸展树 模板题
- bzoj 1500 splay伸展树
- Splay伸展树&模板
- 伸展树(splay)模板
- 伸展树模板
- 伸展树模板题
- 伸展树模板
- 伸展树模板
- bzoj 1251 简单伸展树
- hdu 1890 伸展树区间翻转
- hdu 1890 Robotic Sort(伸展树)
- HDU 1890Robotic Sort 伸展树
- Splay伸展树模板总结
- HDU4453(伸展树模板题)
- 伸展树模版题 hdu
- hdu 4453 Looploop (伸展树)
- nefuoj 8 二倍
- Mock以及Mockito的使用
- Target runtime com.genuitec.runtime.generic.jee60 is not def——已解决
- 从头开始学习yii2---5.完善注册接口
- VC/MFC获取编辑框的值的几种方法
- 伸展树模板(BZOJ 1500,UVALive 3961 HDU 1890)
- socket编程TCP
- linux socket各种函数
- 区块链开发(八)以太坊不同语言客户端地址
- Linux下查看系统版本号信息的方法
- angular原理及模块简介
- struts2工作原理简介
- Linux BT下载(1)-基础入门
- Iterator