Processing math: 100%
NEERC2018 K. King Kog’s Reception

NEERC2018 K. King Kog’s Reception

题目链接

http://codeforces.com/contest/1089/problem/K

题目大意

国王给前来拜访的骑士设计了一个队列。如果他们到的时候队列里面有其他人,那么他就会排在后面,否则会直接去拜访。有 q 次询问,操作一为在 t 时刻加入一个拜访时间为 d 的骑士。操作二为删除一个骑士。操作三为询问如果公主 t 时刻来,那么她需要等多长时间才能拜访到国王。

题目分析

这道题很明显是一道数据结构题。

首先考虑,需要知道什么信息,使得 [l, mid](mid, r] 的区间可以合并并能获取到有用的信息。对题目有直接帮助的显然是区间的结束时间。那么考虑到合并区间的问题,显然还需要记录每个区间的开始时间,还有中间空白的区域。那么如果前面区间等待的时间已经影响到后面的区间,首先会占用后面区间中的空白区域,都占用完了之后,才会推迟最终结束时间。如此一来,可以使用线段树或者平衡树维护即可。

训练赛时队友使用的是线段树,以下代码为赛后重写的平衡树版本。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <ctime>
using namespace std;
const int maxn = 3e5 + 5;
int n, m, q;
int opt[maxn];
struct ex {
long long st;
long long ed;
long long blank;
int init(long long t, long long d){
st = t;
ed = t + d;
blank = 0;
return 0;
}
};
ex exmerge(ex x, ex y){
ex ret;
if(x.st == 0){
return y;
}
if(y.st == 0){
return x;
}
if(x.ed < y.st){
ret.st = x.st;
ret.ed = y.ed;
ret.blank = x.blank + y.blank + y.st - x.ed;
}else{
ret.st = x.st;
ret.ed = y.ed + max(x.ed - y.st - y.blank, 0ll);
ret.blank = x.blank + y.blank - min(x.ed - y.st, y.blank);
}
return ret;
}
struct node {
long long t;
long long d;
ex x;
int fix;
int c[2];
int init(long long tt, long long dd){
t = tt;
d = dd;
fix = rand();
c[0] = c[1] = 0;
x.init(tt, dd);
return 0;
}
};
node tree[maxn * 2];
int tc = 0;
int root = 0;
int read(){
int x;
scanf("%d", &x);
return x;
}
int merge(int pos){
tree[pos].x.init(tree[pos].t, tree[pos].d);
if(tree[pos].c[0]){
tree[pos].x = exmerge(tree[tree[pos].c[0]].x, tree[pos].x);
}
if(tree[pos].c[1]){
tree[pos].x = exmerge(tree[pos].x, tree[tree[pos].c[1]].x);
}
return 0;
}
int rotate(int &pos, int d){
int c = tree[pos].c[d];
tree[pos].c[d] = tree[c].c[!d];
tree[c].c[!d] = pos;
merge(pos);
merge(c);
pos = c;
return 0;
}
int insert(int &pos, long long t, long long d){
if(!pos){
pos = ++tc;
tree[pos].init(t, d);
}else{
int dr = tree[pos].t < t;
insert(tree[pos].c[dr], t, d);
if(tree[pos].fix < tree[tree[pos].c[dr]].fix){
rotate(pos, dr);
}
merge(pos);
}
return 0;
}
int remove(int &pos, long long t){
if(tree[pos].t != t){
int d = tree[pos].t < t;
remove(tree[pos].c[d], t);
merge(pos);
}else{
if(!tree[pos].c[0]){
pos = tree[pos].c[1];
}else if(!tree[pos].c[1]){
pos = tree[pos].c[0];
}else{
int d = tree[tree[pos].c[0]].fix < tree[tree[pos].c[1]].fix;
rotate(pos, d);
remove(tree[pos].c[!d], t);
merge(pos);
}
}
return 0;
}
ex query(int &pos, long long t){
ex ret;
if(!pos){
ret.init(0, 0);
}else{
ret.init(tree[pos].t, tree[pos].d);
if(tree[pos].t > t){
ret = query(tree[pos].c[0], t);
}else if(tree[pos].t == t){
ret = exmerge(tree[tree[pos].c[0]].x, ret);
}else{
ret = exmerge(exmerge(tree[tree[pos].c[0]].x, ret), query(tree[pos].c[1], t));
}
}
return ret;
}
long long getans(long long t){
ex ret = query(root, t);
return max(ret.ed - t, 0ll);
}
int main(){
int i, j;
char op;
int x, y;
srand(time(0));
q = read();
for(i=1;i<=q;i++){
scanf(" %c", &op);
if(op == '+'){
x = read();
y = read();
opt[i] = x;
insert(root, x, y);
}else if(op == '-'){
x = read();
remove(root, opt[x]);
}else{
x = read();
printf("%lld\n", getans(x));
}
}
return 0;
}
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <ctime> using namespace std; const int maxn = 3e5 + 5; int n, m, q; int opt[maxn]; struct ex { long long st; long long ed; long long blank; int init(long long t, long long d){ st = t; ed = t + d; blank = 0; return 0; } }; ex exmerge(ex x, ex y){ ex ret; if(x.st == 0){ return y; } if(y.st == 0){ return x; } if(x.ed < y.st){ ret.st = x.st; ret.ed = y.ed; ret.blank = x.blank + y.blank + y.st - x.ed; }else{ ret.st = x.st; ret.ed = y.ed + max(x.ed - y.st - y.blank, 0ll); ret.blank = x.blank + y.blank - min(x.ed - y.st, y.blank); } return ret; } struct node { long long t; long long d; ex x; int fix; int c[2]; int init(long long tt, long long dd){ t = tt; d = dd; fix = rand(); c[0] = c[1] = 0; x.init(tt, dd); return 0; } }; node tree[maxn * 2]; int tc = 0; int root = 0; int read(){ int x; scanf("%d", &x); return x; } int merge(int pos){ tree[pos].x.init(tree[pos].t, tree[pos].d); if(tree[pos].c[0]){ tree[pos].x = exmerge(tree[tree[pos].c[0]].x, tree[pos].x); } if(tree[pos].c[1]){ tree[pos].x = exmerge(tree[pos].x, tree[tree[pos].c[1]].x); } return 0; } int rotate(int &pos, int d){ int c = tree[pos].c[d]; tree[pos].c[d] = tree[c].c[!d]; tree[c].c[!d] = pos; merge(pos); merge(c); pos = c; return 0; } int insert(int &pos, long long t, long long d){ if(!pos){ pos = ++tc; tree[pos].init(t, d); }else{ int dr = tree[pos].t < t; insert(tree[pos].c[dr], t, d); if(tree[pos].fix < tree[tree[pos].c[dr]].fix){ rotate(pos, dr); } merge(pos); } return 0; } int remove(int &pos, long long t){ if(tree[pos].t != t){ int d = tree[pos].t < t; remove(tree[pos].c[d], t); merge(pos); }else{ if(!tree[pos].c[0]){ pos = tree[pos].c[1]; }else if(!tree[pos].c[1]){ pos = tree[pos].c[0]; }else{ int d = tree[tree[pos].c[0]].fix < tree[tree[pos].c[1]].fix; rotate(pos, d); remove(tree[pos].c[!d], t); merge(pos); } } return 0; } ex query(int &pos, long long t){ ex ret; if(!pos){ ret.init(0, 0); }else{ ret.init(tree[pos].t, tree[pos].d); if(tree[pos].t > t){ ret = query(tree[pos].c[0], t); }else if(tree[pos].t == t){ ret = exmerge(tree[tree[pos].c[0]].x, ret); }else{ ret = exmerge(exmerge(tree[tree[pos].c[0]].x, ret), query(tree[pos].c[1], t)); } } return ret; } long long getans(long long t){ ex ret = query(root, t); return max(ret.ed - t, 0ll); } int main(){ int i, j; char op; int x, y; srand(time(0)); q = read(); for(i=1;i<=q;i++){ scanf(" %c", &op); if(op == '+'){ x = read(); y = read(); opt[i] = x; insert(root, x, y); }else if(op == '-'){ x = read(); remove(root, opt[x]); }else{ x = read(); printf("%lld\n", getans(x)); } } return 0; }
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <ctime>

using namespace std;

const int maxn = 3e5 + 5;

int n, m, q;

int opt[maxn];

struct ex {
	long long st;
	long long ed;
	long long blank;
	
	int init(long long t, long long d){
		st = t;
		ed = t + d;
		blank = 0;
		return 0;
	}
};

ex exmerge(ex x, ex y){
	ex ret;
	
	if(x.st == 0){
		return y;
	}
	if(y.st == 0){
		return x;
	}
	
	if(x.ed < y.st){
		ret.st = x.st;
		ret.ed = y.ed;
		ret.blank = x.blank + y.blank + y.st - x.ed;
	}else{
		ret.st = x.st;
		ret.ed = y.ed + max(x.ed - y.st - y.blank, 0ll);
		ret.blank = x.blank + y.blank - min(x.ed - y.st, y.blank);
	}
	
	return ret;
}

struct node {
	long long t;
	long long d;
	ex x;
	int fix;
	int c[2];
	
	int init(long long tt, long long dd){
		t = tt;
		d = dd;
		fix = rand();
		c[0] = c[1] = 0;
		x.init(tt, dd);
		return 0;
	}
};

node tree[maxn * 2];
int tc = 0;
int root = 0;

int read(){
	int x;
	scanf("%d", &x);
	return x;
}

int merge(int pos){
	tree[pos].x.init(tree[pos].t, tree[pos].d);
	if(tree[pos].c[0]){
		tree[pos].x = exmerge(tree[tree[pos].c[0]].x, tree[pos].x);
	}
	
	if(tree[pos].c[1]){
		tree[pos].x = exmerge(tree[pos].x, tree[tree[pos].c[1]].x);
	}
	return 0;
}

int rotate(int &pos, int d){
	int c = tree[pos].c[d];
	
	tree[pos].c[d] = tree[c].c[!d];
	tree[c].c[!d] = pos;
	
	merge(pos);
	merge(c);
	
	pos = c;
	
	return 0;
}

int insert(int &pos, long long t, long long d){
	if(!pos){
		pos = ++tc;
		tree[pos].init(t, d);
	}else{
		int dr = tree[pos].t < t;
		insert(tree[pos].c[dr], t, d);
		
		if(tree[pos].fix < tree[tree[pos].c[dr]].fix){
			rotate(pos, dr);
		}
		
		merge(pos);
	}
	
	return 0;
}

int remove(int &pos, long long t){
	if(tree[pos].t != t){
		int d = tree[pos].t < t;
		remove(tree[pos].c[d], t);
		merge(pos);
	}else{
		if(!tree[pos].c[0]){
			pos = tree[pos].c[1];
		}else if(!tree[pos].c[1]){
			pos = tree[pos].c[0];
		}else{
			int d = tree[tree[pos].c[0]].fix < tree[tree[pos].c[1]].fix;
			rotate(pos, d);
			remove(tree[pos].c[!d], t);
			merge(pos);
		}
	}
	
	return 0;
}

ex query(int &pos, long long t){
	ex ret;
	
	if(!pos){
		ret.init(0, 0);
	}else{
		ret.init(tree[pos].t, tree[pos].d);
		if(tree[pos].t > t){
			ret = query(tree[pos].c[0], t);
		}else if(tree[pos].t == t){
			ret = exmerge(tree[tree[pos].c[0]].x, ret);
		}else{
			ret = exmerge(exmerge(tree[tree[pos].c[0]].x, ret), query(tree[pos].c[1], t));
		}
	}
	
	return ret;
}

long long getans(long long t){
	ex ret = query(root, t);
	return max(ret.ed - t, 0ll);
}

int main(){
	int i, j;
	char op;
	int x, y;
	
	srand(time(0));
	
	q = read();
	
	for(i=1;i<=q;i++){
		scanf(" %c", &op);
		if(op == '+'){
			x = read();
			y = read();
			opt[i] = x;
			insert(root, x, y);
		}else if(op == '-'){
			x = read();
			remove(root, opt[x]);
		}else{
			x = read();
			printf("%lld\n", getans(x));
		}
	}
	
	return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据