标签存档: 线段树

[POI IX] Railways

IX Olimpiada Informatyczna 2001/2002

Task: kol
Author: Tomasz Waleń
Railways

I stage contest

Byteotian State Railways decided to keep up with the times and introduce to their offer an InterCity connection. Because of lack of efficient engines, clean carriages and straight tracks it was possible to establish only one such a connection. The lack of any computer system for seat reservation was another obstacle. Writing the main part of this system is your task.

For simplicity we assume that the InterCity connection runs through c cities numbered successively from 1 to c (the starting city has the number 1, and c is the number of the ending city). There are s seats in the train and transporting more passengers between any two successive stations is not allowed.

The computer system is to receive successive requests and determine whether they may be fulfilled. A request is accepted when in the given section of the railway line there is enough vacant seats in the train. Otherwise it is rejected. Partial accepting of a request is not allowed, e.g. for a part of a route or for less passengers. After accepting a request, the number of vacant seats in the train is updated. The requests are processed successively in the order of coming.

Task

Write a program which:

  • reads from the text file kol.in the description of the connection and a list of requested reservations,
  • computes which requests will be accepted, and which will be rejected,
  • writes to the text file kol.out the answers to all the requests.

Input

In the first line of the text file kol.in there are three integers c, s and r (1<=c<=60 000, 1<=s<=60 000, 1<=r<=60 000) separated by single spaces. The numbers denote respectively: the number of cities on the railway line, the number of seats in the train, and the number of requests. In the following r lines there are consecutive requests written. In the line of number i+1 there is the i-th request described. The description consists of three integers o, d and n (1<=o<d<=c, 1<=n<=s) separated by single spaces. They denote: the number of the station of origin, the number of the destination station and the requested number of seats, respectively.

Output

Your program should write r lines to the text file kol.out. In the i-th line there should be exactly one character:

  • T (for “yes”) – if the i-th request is accepted,
  • N (for “no”) – otherwise.

Solution

又是一道线段树。挖个坑先 ^_^

终于过了……反复不过竟然是因为数据用的太小了(unsigned short),后来改成long就AC了……一直觉得应该没问题啊,结果还是溢出了。看来像unsigned啊、short啊这种关键字还是慎用为妙。

从这个题可以学到线段树通过标记来减少不必要修改的思想——其实上一道zju的就是这样的。

代码:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cassert>
using namespace std;
FILE *fin = fopen("kol.in","r"),
	*fout = fopen("kol.out","w");
const long A=1,B=60000;
long C,S,R;//城市数目、座位总数、请求数

struct STNode{
	long a,b,lch,rch,avail,sold;
	STNode(long _a, long _b){
		a=_a;
		b=_b;
		avail=S;
		sold=0;
		lch=rch=0;
	}
	STNode(void){}
}STree[(B-A)<<1];

void ST_Build(long a, long b){
	static unsigned i=1;
	unsigned now=i++;
	STree[now]=STNode(a,b);
	if(b-a>1){
		STree[now].lch=i;
		ST_Build(a,(a+b)>>1);
		STree[now].rch=i;
		ST_Build((a+b)>>1,b);
	}
}

void ST_Clear(long i){	//清空节点i的sold域
	if(i==0)	return;
	STree[STree[i].lch].sold+=STree[i].sold;
	STree[STree[i].rch].sold+=STree[i].sold;
	STree[i].avail-=STree[i].sold;
	STree[i].sold=0;
}
bool ST_Check(long a, long b, long s, long i){
	if(STree[i].sold>0)	ST_Clear(i);
	if(a<=STree[i].a&&STree[i].b<=b)	return (STree[i].avail>=s);
	else{
		bool flag1=true,flag2=true;
		if(a<((STree[i].a+STree[i].b)>>1))	flag1=ST_Check(a,b,s,STree[i].lch);
		if(b>((STree[i].a+STree[i].b)>>1))	flag2=ST_Check(a,b,s,STree[i].rch);
		return (flag1&&flag2);
	}
}
void ST_Delete(long a,long b, long s, long i){
	if(STree[i].sold>0)	ST_Clear(i);
	if(a<=STree[i].a&&STree[i].b<=b){
		assert(STree[i].avail>=s);
		STree[i].avail-=s;
		STree[STree[i].lch].sold+=s;
		STree[STree[i].rch].sold+=s;
	}else{
		if(a<((STree[i].a+STree[i].b)>>1))	ST_Delete(a,b,s,STree[i].lch);
		else	ST_Clear(STree[i].lch);
		if(b>((STree[i].a+STree[i].b)>>1))	ST_Delete(a,b,s,STree[i].rch);
		else	ST_Clear(STree[i].rch);
		STree[i].avail=min(STree[STree[i].lch].avail,STree[STree[i].rch].avail);
	}
}

int main()
{
	fscanf(fin,"%d %d %d\n",&C,&S,&R);
	ST_Build(A,B);
	for(int r=0,o,d,n;r<R;r++){
		fscanf(fin,"%d %d %d\n",&o,&d,&n);
		if(ST_Check(o,d,n,1)){
			fprintf(fout,"T\n");
			ST_Delete(o,d,n,1);
		}else	fprintf(fout,"N\n");
	}
	fclose(fin);
	fclose(fout);
	return 0;
}

P.S.不知道是不是我rp用完了,反正现在cena也不给我好好干活了。只要测pas的程序一律显示“崩溃(访问无效内存)”,重装cena、fp都没用,郁闷。就搞了两个评测系统,一个是HWD的,感觉很烦琐,不知道怎么评测C的程序;一个就是这个雅礼ZYF的系统,直接评测exe,好像不支持交互。下面是此程序生成的成绩单,我比标程慢……

成绩单

编号: standard; 总得分: 130; 总耗时: 1.21

试题名称: Problem A; 测试例数: 13; 本题得分: 130.0; 本题耗时: 1.21

例号 用时 评测结果 得分
1 0.02 正确 10
2 0.02 正确 10
3 0.02 正确 10
4 0.02 正确 10
5 0.02 正确 10
6 0.36 正确 10
7 0.03 正确 10
8 0.08 正确 10
9 0.02 正确 10
10 0.09 正确 10
11 0.11 正确 10
12 0.03 正确 10
13 0.39 正确 10

编号: tomtung; 总得分: 130; 总耗时: 1.61

试题名称: Problem A; 测试例数: 13; 本题得分: 130.0; 本题耗时: 1.61

例号 用时 评测结果 得分
1 0.03 正确 10
2 0.03 正确 10
3 0.03 正确 10
4 0.03 正确 10
5 0.03 正确 10
6 0.44 正确 10
7 0.05 正确 10
8 0.09 正确 10
9 0.09 正确 10
10 0.09 正确 10
11 0.16 正确 10
12 0.06 正确 10
13 0.48 正确 10

[ZOJ1610]Count the Colors

Count the Colors


Time limit: 1 Seconds   Memory limit: 32768K
Total Submit: 2977   Accepted Submit: 1000


Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you can see at last.

Input

The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.

Output

Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

If some color can’t be seen, you shouldn’t print it.

Print a blank line after every dataset.

Author: Standlove

Source: ZOJ Monthly, May 2003

Solution:

第一个用线段树过的题目啊~~呵呵。基础题目,虽然对我来说并不简单。在处理最后数线段条数的问题上颇费了些周折,先是问大牛,结果没搞懂,就自力更生地写出来了。。。

话说特别巧,我刚好是第1000个过这道题的人,哈哈

我的时空消耗:

代码(发现我越来越不爱写注释了):

#include <cstdio>
#include <cassert>
#include <cstring>
#define NDEBUG
//#define FILE_IO
using namespace std;
#ifdef FILE_IO
	FILE *fin = fopen("INPUT.TXT","r");
	FILE *fout= fopen("OUTPUT.TXT","w");
#else
	FILE *fin = stdin;
	FILE *fout= stdout;
#endif
const unsigned short min_a=0, max_b=8000;
unsigned short N;
struct STNode{
	unsigned short a,b,lch,rch;
	short color;	//-1为无色,-2为杂色
	STNode(unsigned short __a, unsigned short __b){
		a=__a;
		b=__b;
		color=-1;
		lch=rch=0;
	}
	STNode(void){;}
};
STNode STree[(max_b-min_a)*2];
unsigned short i;
void ST_Build(unsigned short a, unsigned short b){
	unsigned now=i++;
	STree[now]=STNode(a,b);
	if(b-a>1){
		STree[now].lch=i;
		ST_Build(a,(a+b)>>1);
		STree[now].rch=i;
		ST_Build((a+b)>>1,b);
	}
}
void ST_Insert(unsigned short i,unsigned short a, unsigned short b, short color){
	assert(a<b);
	if(STree[i].color==color)	return;
	if(a<=STree[i].a&&STree[i].b<=b)	STree[i].color=color;
	else{
		if(STree[i].color!=-2&&STree[i].color!=-1){
			STree[STree[i].lch].color=STree[i].color;
			STree[STree[i].rch].color=STree[i].color;
		}
		STree[i].color=-2;
		unsigned short m=((STree[i].a+STree[i].b)>>1);
		if(a<m)	ST_Insert(STree[i].lch,a,b,color);
		if(b>m)	ST_Insert(STree[i].rch,a,b,color);
	}
}
unsigned colors[8001];
void SgCount(unsigned short i, short &a_color, short &b_color){
	//在在color中增加以i节点为根的ST中各色的线段数目
	//并返回最左、最右端的颜色分别为a_color和b_color
	if(STree[i].color!=-2){
		a_color=b_color=STree[i].color;
		if(STree[i].color!=-1)	colors[STree[i].color]++;
	}
	else{
		short m1_color,m2_color;
		SgCount(STree[i].lch,a_color,m1_color);
		SgCount(STree[i].rch,m2_color,b_color);
		if(m1_color==m2_color&&m1_color!=-1)
			colors[m1_color]--;
	}
}
int main()
{
	while(fscanf(fin,"%d\n",&N)==1){
		i=1;
		ST_Build(min_a,max_b);
		for(int i=0,a,b,color;i<N;i++){
			fscanf(fin,"%d %d %d\n",&a,&b,&color);
			ST_Insert(1,a,b,color);
		}
		memset(colors,'\0',sizeof(colors));
		short a_color,b_color;
		SgCount(1,a_color,b_color);
		for(int i=0;i<=8000;i++)
			if(colors[i]!=0)	fprintf(fout,"%d %d\n",i,colors[i]);
		fprintf(fout,"\n");
	}
	return 0;
}

标签云

豆瓣