2018牛客多校第三场C

上来没读清题,写了个双向链表一阵模拟,对着空气用力了一小时,读清题后就gg了。

搜索题解,splay,wtf??我不会啊!!嗯?rope,好东西,先码一下。

这是什么东西,其实就是一个可以比较高效的地实现区间转换的东西

rope的基本操作

#include <ext/rope>
 
using namespace __gnu_cxx;
//以上两个东西是使用rope需要用的
 
//1.声明
rope<int>t;
//2.初始化
t.clear();
//3.操作
 
t.push_back(x);//在末尾添加x(元素)
 
t.insert(pos,x);//在pos位置(pos=0...t.size()-1)插入x(元素/rope)
 
t.copy(pos,x,to);//把rope从pos开始的x个元素,覆盖到指针node* to中
 
t.replace(pos,x,y);//从pos开始的x个换成y(元素/rope)
 
t.erase(pos,x);//从pos开始删除x个
 
t.substr(pos,x);//提取pos开始x个
 
t.at(pos)/t[pos];//访问pos位置元素

下面是代码

#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;

rope <int> s, tmp;

int main(){
	int n, m;
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i ++)
		s. push_back(i);
	int l, r;
	while(m --){
		scanf("%d %d", &l, &r);
		tmp = s. substr(l - 1, r);
		s. erase(l - 1, r);
		s = tmp + s;
	}
	for(int i = 0; i < n; i ++){
		printf("%d%c", s[i], i == n - 1 ? '\n' : ' ');
	}
	return 0;
}

splay的代码,emmm,待我学习一下再来补上233

早起码了一早上,感觉自己要上天~

只要注意到区间前提的操作可以通过三次区间翻转实现就可以套splay了

#include <bits/stdc++.h>
#define Key_value ch[ch[root][1]][0] 
using namespace std;

const int N = 500500;
const int inf = 0x3f3f3f3f;

int pre[N], ch[N][2], key[N], size[N];
int sum[N], rev[N], same[N];
int lx[N], rx[N], mx[N];
int root, tot1;
int s[N], tot2;
int a[N];
int n, q;

//debug 部分
void Treavel(int x){
	if(x){
		Treavel(ch[x][0]);
		printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d key=%2d, size= %2d, sum=%2d,rev=%2d same=%2d lx=%2d rx=%2d mx=%2d\n",x,ch[x][0],ch[x][1],pre[x],key[x],size[x],sum[x],rev[x],same[x],lx[x],rx[x],mx[x]);
		Treavel(ch[x][1]);
	}
} 
void debug(){
	printf("root%d\n", root);
	Treavel(root);
}
void NewNode(int &r, int father, int k){
	if(tot2)
		r = s[tot2 --];
	else
		r = ++ tot1;
	pre[r] = father;
	ch[r][0] = ch[r][1] = 0;
	key[r] = k;
	sum[r] = k;
	rev[r] = same[r] = 0;
	lx[r] = rx[r] = mx[r] = k;
	size[r] = 1;	
}
void Updata_Same(int r, int v){
	if(! r)
		return ;
	key[r] = v;
	sum[r] = v * size[r];
	lx[r] = rx[r] = mx[r] = max(v, v * size[r]);
	same[r] = 1;
}
void Updata_Rev(int r){
	if(! r)
		return ;
	swap(ch[r][0], ch[r][1]);
	swap(lx[r], rx[r]);
	rev[r] ^= 1;
}
void Push_Up(int r){
	int lson = ch[r][0], rson = ch[r][1];
	size[r] = size[lson] + size[rson] + 1;
	sum[r] = sum[lson] + sum[rson] + key[r];
	lx[r] = max(lx[lson], sum[lson] + key[r] + max(0, lx[rson]));
	rx[r] = max(rx[rson], sum[rson] + key[r] + max(0, rx[lson]));
	mx[r] = max(0, rx[lson] + key[r] + max(0, lx[rson]));
	mx[r] = max(mx[r], max(mx[lson], mx[rson]));
}
void Push_Down(int r){
	if(same[r]){
		Updata_Same(ch[r][0], key[r]);
		Updata_Same(ch[r][1], key[r]);
		same[r] = 0;
	}
	if(rev[r]){
		Updata_Rev(ch[r][0]);
		Updata_Rev(ch[r][1]);
		rev[r] = 0;
	}
}
void Build(int &x, int l, int r, int father){
	if(l > r)
		return ;
	int mid = (l + r) / 2;
	NewNode(x, father, a[mid]);
	Build(ch[x][0], l, mid - 1, x);
	Build(ch[x][1], mid + 1, r, x);
	Push_Up(x);
}
void Init(){
	root = tot1 = tot2 = 0;
	ch[root][0] = ch[root][1] = pre[root] = size[root] = same[root] = rev[root] = sum[root] = key[root] = 0;
	lx[root] = rx[root] = mx[root] = -inf;
	NewNode(root, 0, -1);
	NewNode(ch[root][1], root, -1);
	for(int i = 0; i < n; i ++)
		a[i] = i + 1;
	Build(Key_value, 0, n - 1, ch[root][1]);
	Push_Up(ch[root][1]);
	Push_Up(root);
}
void Rotate(int x, int kind){
	int y = pre[x];
	Push_Down(y);
	Push_Down(x);
	ch[y][! kind] = ch[x][kind];
	pre[ch[x][kind]] = y;
	if(pre[y])
		ch[pre[y]][ch[pre[y]][1] == y] = x;
		pre[x] = pre[y];
		ch[x][kind] = y;
		pre[y] = x;
		Push_Up(y);
}
void Splay(int r, int goal){
	Push_Down(r);
	while(pre[r] != goal){
		if(pre[pre[r]] == goal){
			Push_Down(pre[r]);
			Push_Down(r);
			Rotate(r, ch[pre[r]][0] == r);
		}
		else{
			Push_Down(pre[pre[r]]);
			Push_Down(pre[r]);
			Push_Down(r);
			int y = pre[r];
			int kind = ch[pre[y]][0] == y;
			if(ch[y][kind] == r){
				Rotate(r, ! kind);
				Rotate(r, kind);
			}
			else{
				Rotate(y, kind);
				Rotate(r, kind); 
			}
		}
	}
	Push_Up(r);
	if(goal == 0)
		root = r;
}
int Get_Kth(int r, int k){
	Push_Down(r);
	int t = size[ch[r][0]] + 1;
	if(t == k)
		return r;
	if(t > k)
		return Get_Kth(ch[r][0], k);
	else
		return Get_Kth(ch[r][1], k - t);
}

//在第POS个数后插入tot个数 
void Insert(int pos, int tot){
	for(int i = 0; i < tot; i ++)
		scanf("%d", &a[i]);
		Splay(Get_Kth(root, pos + 1), 0);
		Splay(Get_Kth(root, pos + 2), root);
		Build(Key_value, 0, tot - 1, ch[root][1]);
		Push_Up(ch[root][1]);
		Push_Up(root);
}
void erase(int r){
	if(! r)
		return ;
	s[++ tot2] = r;
	erase(ch[r][0]);
	erase(ch[r][1]);
}
//从第pos个数开始连续删除tot个数
void Delete(int pos, int tot){
	Splay(Get_Kth(root, pos), 0);
	Splay(Get_Kth(root, pos + tot + 1), root);
	erase(Key_value);
	pre[Key_value] = 0;
	Push_Up(ch[root][1]);
	Push_Up(root);
} 
//从第pos个数开始连续的tot个数修改为c
void Make_Same(int pos, int tot, int c){
	Splay(Get_Kth(root, pos), 0);
	Splay(Get_Kth(root, pos + tot + 1), root);
	Updata_Same(Key_value, c);
	Push_Up(ch[root][1]);
	Push_Up(root);
} 
//反转 
void Reverse(int pos, int tot){
	Splay(Get_Kth(root, pos), 0);
	Splay(Get_Kth(root, pos + tot + 1), root);
	Updata_Rev(Key_value);
	Push_Up(ch[root][1]);
	Push_Up(root);
}
//求和
int Get_Sum(int pos, int tot){
	Splay(Get_Kth(root, pos), 0);
	Splay(Get_Kth(root, pos + tot + 1), root);
	return sum[Key_value];
} 
//得到最大和
int Get_MaxSum(int pos, int tot){
	Splay(Get_Kth(root, pos), 0);
	Splay(Get_Kth(root, pos + tot + 1), root);
	return mx[Key_value];
} 
int cnt;
void Inorder(int r){
	if(! r)
		return ;
	Push_Down(r);
	Inorder(ch[r][0]);
	if(key[r] != -1)
		printf("%d%c", key[r], ++cnt == n ? '\n' : ' ');
	Inorder(ch[r][1]);
}
int main(){
	while(scanf("%d %d", &n, &q) == 2){
		Init();
		int x, y;
		while(q --){
			scanf("%d %d", &x, &y);
			Reverse(1, y + x - 1);
			Reverse(1, y);
			Reverse(y + 1, x - 1);
		}
		cnt = 0;
		Inorder(root);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/81461980