您的位置:首页 > 其它

南邮 OJ 1409 售票系统

2015-08-05 15:29 375 查看

售票系统

时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte

总提交 : 252 测试通过 : 38


比赛描述
某次列车途经C个城市,城市编号依次为1到C,列车上共有S个座位,铁路局规定售出的车票只能是坐票,即车上所有的旅客都有座,售票系统是由计算机执行的,每一个售票申请包含三个参数,分别用O、D、N表示,O为起始站,D为目的地站,N为车票张数,售票系统对该售票申请作出受理或不受理的决定,只有在从O到D的区段内列车上都有N个或N个以上的空座位时该售票申请才被受理,请你写一个程序,实现这个自动售票系统。

输入

输入第一行包含三个用空格隔开的整数C、S和R,其中1<=C<=60000,1<=S<=60000,1<=R<=60000,C为城市个数,S为列车上的座位数,R为所有售票申请总数。接下来的R行每行为一个售票申请,用三个由空格隔开的整数O,D和N表示,O为起始站,D为目的地站,N为车票站数,其中1<=0<D<=C,1<=N<=C,所有的售票申请按申请的时间从早到晚给出。

输出

输出共有R行,每行输出一个“YES”或“NO”,表示当前的售票申请被受理或不被受理。

样例输入

4 6 4

1 4 2

1 3 2

2 4 3

1 2 3

样例输出

YES

YES

NO

NO

提示

题目来源

JSOI2010

#include<stdio.h>
#define MAX_N 60010

struct TreeNode{
int left;		//最左边线段编号
int right;		//最右端线段编号
int maxUsed;	//本跨度线段最多被使用的次数
int childToAdd;	//本节点已经加过,但是孩子节点没有被加过,等待查询时加的使用计数
}nodes[MAX_N<<2];	//4倍容量肯定够存储

//构建以节点i为根节点的树
void build(int i, int left, int right){
nodes[i].left = left;
nodes[i].right = right;
nodes[i].maxUsed = 0;
nodes[i].childToAdd = 0;
if(left != right){
int mid = (left+right)>>1;
build(i<<1|1, left, mid);
build((i+1)<<1, mid+1, right);
}
}

//[left,right]区间使用计数增加used,更新树
void add(int i, int left, int right, int used){
if(nodes[i].left==left && nodes[i].right==right){
nodes[i].maxUsed += used;
nodes[i].childToAdd += used;		//先存着,向孩子插入时 或者 查询时更新
}else{
int lChild = i<<1|1;
int rChild = (i+1)<<1;
int temp = nodes[i].childToAdd;		//插入子节点之前,先将childToAdd加到孩子节点
if(temp){
nodes[lChild].maxUsed += temp;
nodes[lChild].childToAdd += temp;
nodes[rChild].maxUsed += temp;
nodes[rChild].childToAdd += temp;
nodes[i].childToAdd = 0;
}
int mid = (nodes[i].left+nodes[i].right)>>1;
if(mid>=left){						//RE 需要更新左子树
temp = right;
if(temp>mid){
temp = mid;
}
add(lChild, left, temp, used);
}
if(mid+1<=right){					//RE 需要更新右子数
temp = left;
if(temp<mid+1){
temp = mid+1;
}
add(rChild, temp, right, used);
}
if(nodes[lChild].maxUsed<nodes[rChild].maxUsed){
nodes[i].maxUsed = nodes[rChild].maxUsed;
}else{								//更新完子树之后,更新当前节点最大使用次数
nodes[i].maxUsed = nodes[lChild].maxUsed;
}
}
}

//查询[left,right]中最大使用次数
int maxUsed(int i, int left, int right){
if(nodes[i].left==left && right==nodes[i].right){
return nodes[i].maxUsed;
}
int lChild = i<<1|1;
int rChild = (i+1)<<1;
int temp = nodes[i].childToAdd;			//查询子节点之前,先将childToAdd加到孩子节点
if(temp){
nodes[lChild].maxUsed += temp;
nodes[lChild].childToAdd += temp;
nodes[rChild].maxUsed += temp;
nodes[rChild].childToAdd += temp;
nodes[i].childToAdd = 0;
}
int mid = (nodes[i].left+nodes[i].right)>>1;
if(mid>=right){							//区间包含在左子树之内
return maxUsed(lChild, left, right);
}
if(mid+1<=left){						//区间包含在右子树之内
return maxUsed(rChild, left, right);
}
int result = maxUsed(lChild, left, mid);
temp = maxUsed(rChild, mid+1, right);
if(result<temp){
result = temp;
}
return result;
}

int main(){
int C,S,R,O,D,N;
scanf("%d%d%d",&C,&S,&R);
build(0,1,C-1);							//第一段路编号1,最后一段路编号C-1,共C-1段路,C个站点
while(R--){
scanf("%d%d%d",&O,&D,&N);
if(maxUsed(0,O,D-1)+N<=S){
printf("YES\n");
add(0,O,D-1,N);
}else{
printf("NO\n");
}
}
}

/*Time Limit Exceed at Test 11
#include<stdio.h>
int a[60001];
int main(){
int C,S,R,O,D,N,i;
scanf("%d%d%d",&C,&S,&R);
for(i=1;i<=C;i++){
a[i] = S;
}
while(R--){
scanf("%d%d%d",&O,&D,&N);
for(i=O;i<D;i++){
if(a[i]<N){
break;
}
}
if(i<D){
printf("NO\n");
}else{
printf("YES\n");
for(i=O;i<D;i++){
a[i] -= N;
}
}
}
}
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: