Problem 2101 大三的美好时光
Problem Description
依稀记得自己踏入福大时学长学姐的甜美笑脸,可是一转眼的功夫自己就是大三的学长了。时间匆匆而过也就算了,bluesun痛苦的是,到大三了校选课还没有修满,再加上院选和必修课,bluesun的大三注定是异常辛苦的一年。
Bluesun总是喜欢把要做的事情在最短的时间里做完,所以他决定在必修课必选之外,选择一种使自己可以得到最多学分的方案(不管是院选的学分还是校选的,bluesun只要求学分尽量多)。
Input
数据有多组,请处理到文件结尾。
每组数据的第一行为n(n表示有n门课程可供选择)接下来n行,每行4个整数,t 、l、 r和 v,如果t==0,则表示这门课程是必修课,否则为院选课或者是校选课,l和r表示该门课程占用的时间段为[l,r],v表示该门课程占几个学分。
输入数据均为整数,并且保证必修课的时间不会有交叉,1<=n<=100000,0<=v<=10000,1<=l<=r<=2^30。
Output
每组测试输出一个整数,每个整数占1行,表示bluesun这个学期最多可以修多少个学分。
Sample Input
11 1 1 2
Sample Output
2
先hash预处理,把L,R的值降下来。最大为100000*2 。
dp[i] 表示在 i 这个时间 为止,可得最大的(选修课)学分。
显然要将课程为R截止的放在vector【R】里面。
判断选修课与必修课没有交点,Last[i] ,表示i 这个时间点的最近一个必修课的截止时间。
int getint(){
char c=getchar();
int t=0;
while(c<'0'||c>'9'){
c=getchar();
}
while(c>='0'&&c<='9'){
t=t*10+c-'0';
c=getchar();
}
return t;
}
const int Max_N = 100008 ;
struct Node{
int T ;
int L ;
int R ;
int V ;
friend bool operator < (const Node & A , const Node &B){
if(A.R != B.R)
return A.R < B.R ;
else
return A.L < B.L ;
}
};
Node course[Max_N] ;
bool visited[Max_N*2+10] ;
int Last[Max_N*2+10] ;
int dp[Max_N*2+10] ;
int N ;
int _hash[Max_N*2+10] ;
struct Edge{
int v ;
int next ;
}edge[Max_N*2+10];
int List[Max_N*2+10] ;
int e_id ;
void add_edge(int u , int v){
edge[e_id].v = v ;
edge[e_id].next = List[u] ;
List[u] = e_id++ ;
}
int main(){
int i , t , j , k , sum , id ;
while(scanf("%d" ,&N) != EOF){
id = 0 ;
for(i = 0 ; i < N ; i++){
course[i].T = getint() ;
course[i].L = getint() ;
course[i].R = getint() ;
course[i].V = getint() ;
_hash[id++] = course[i].L ;
_hash[id++] = course[i].R ;
}
sort(_hash , _hash + id) ;
int Len = unique(_hash , _hash + id) - _hash ;
for(i = 0 ; i < N ; i++){
course[i].L = upper_bound(_hash , _hash + Len ,course[i].L) - _hash ;
course[i].R = upper_bound(_hash , _hash + Len ,course[i].R) - _hash ;
}
sort(course , course+N) ;
memset(visited , 0 , (Len+2)*sizeof(bool)) ;
e_id = 0 ;
memset(List , -1 , (Len+2)*sizeof(int)) ;
for(i = 0 ; i < N ; i++)
add_edge(course[i].R , i) ;
sum = 0 ;
for(i = 0 ; i < N ; i++){
if(!course[i].T){
for(j = course[i].L ; j <= course[i].R ; j++)
visited[j] = 1 ;
sum += course[i].V ;
}
}
int last_id = -1 ;
for(i = 1 ; i <= Len ; i++){
if(visited[i])
last_id = i ;
else
Last[i] = last_id ;
}
memset(dp , 0 , (Len+2)*sizeof(int)) ;
for(i = 1 ; i <= Len ; i++){
if(! visited[i]){
for(j = List[i] ; j != -1 ; j = edge[j].next){
k = edge[j].v ;
if(!course[k].T)
continue ;
if(Last[i] >= course[k].L)
continue ;
dp[i] = max(dp[i] , dp[course[k].L-1] + course[k].V) ;
}
}
dp[i] = max(dp[i] , dp[i-1]) ;
}
printf("%d\n" , sum + *max_element(dp , dp+Len+1)) ;
}
return 0 ;
}