NOI 嘉年华

题目描述
NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。
现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉年华的会场,也可以不安排。
小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。
另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相对较少的嘉年华的活动数量最大。
此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华的活动数量的最大值。
输入输出格式
输入格式:
输入的第一行包含一个整数 n,表示申请的活动个数。
接下来 n 行描述所有活动,其中第 i 行包含两个整数 Si、Ti,表示第 i 个活动从时刻Si开始,持续 Ti的时间。
输出格式:
输出的第一行包含一个整数,表示在没有任何限制的情况下,活动较少的嘉年华的活动数的最大值。
接下来 n 行每行一个整数,其中第 i 行的整数表示在必须选择第 i 个活动的前提下,活动较少的嘉年华的活动数的最大值。
输入输出样例
输入样例#1:

8 2 
1 5 
5 3 
3 2 
5 3 
输出样例#1:






说明
【样例说明】

在没有任何限制的情况下,最优安排可以在一个嘉年华安排活动1, 4,而在另一个嘉年华安排活动3, 5,活动2不安排。


如果输出格式不正确(比如输出不足n+1行),得0分;
如果输出文件第一行不正确,而且后n行至少有一行不正确,得0分;
如果输出文件第一行正确,但后n行至少有一行不正确,得4分;
如果输出文件第一行不正确,但后n行均正确,得6分;

如果输出文件中的n+1行均正确,得10分。

题解:不知为何网上的题解都写得那么复杂……

首先将时刻离散化。

num【i】【j】表示时刻i到j的活动数量

pre【i】【j】表示到地i时刻,其中一个嘉年华A有j个活动,另一个嘉年华B的活动数量的最大值。

suf【i】【j】表示i时刻到末时刻A有j个活动,B的最大活动数量。

如果是第一问,三个数组就搞定了,但还有第二个限制,强制选,那么就定义G[i][j]表示i时刻到j时刻被强制选取后A,B中最小的一个的最大值。

pre【i】【j】=max(pre【i】【j】,max(pre【k】【j】+num【k】【i】,pre【k】【j-num【k】【i】】)(k<i)

suf也是同样的,具体见代码。

//1.7s,BZOJ能过,洛谷TLE 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define N 300000
#define INF 0x3f3f3f3f
using namespace std;
int n,num[500][500],sta[N],top=0,G[500][500],suf[500][500],pre[500][500];
struct node{
	int L,R;
}seg[N];
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&seg[i].L,&seg[i].R);
		seg[i].R+=seg[i].L;
		sta[++top]=seg[i].L;sta[++top]=seg[i].R;
	}
	sort(sta+1,sta+1+top);
	top = unique(sta+1,sta+1+top)-sta-1;
	for(int i=1;i<=n;i++){
		seg[i].L=upper_bound(sta+1,sta+1+top,seg[i].L)-sta-1;
		seg[i].R=upper_bound(sta+1,sta+1+top,seg[i].R)-sta-1;
	}
	for(int i=1;i<=top;i++){//make num[i][j]
		for(int j=1;j<=n;j++)
		    if(seg[j].L>=i)num[i][seg[j].R]++;
		for(int j=i+1;j<=top;j++) num[i][j]+=num[i][j-1];
	}
	memset(pre,-INF,sizeof(pre));memset(suf,-INF,sizeof(suf));
	pre[1][0]=0;
	suf[top][0]=0;
	for(int j=0;j<=n;j++)
		for(int i=1;i<=top;i++)
			for(int k=1;k<=i;k++)
			     pre[i][j]=max(pre[i][j],max(pre[k][j]+num[k][i],pre[k][j-num[k][i]]));
	for(int j=0;j<=n;j++)
	    for(int i=top;i;i--)
	        for(int k=top;k>=i;k--)
	           suf[i][j]=max(suf[i][j],max(suf[k][j]+num[i][k],suf[k][j-num[i][k]]));
	for(int i=1;i<=top;i++)
		for(int j=i;j<=top;j++){
			G[i][j]=~INF;
			for(int x=0,y=n;x<=n;x++){
				while(y>=0 && x+y>(num[i][j]+pre[i][x]+suf[j][y])) y--;
				if(y>=0) G[i][j]=max(G[i][j],x+y);
			}
		}
	int ans=-1;
	for(int i=0;i<=n;i++) ans=max(ans,min(suf[1][i],i));
//	cout<<top<<"   "<<n<<endl;
	printf("%d\n",ans);
    for(int i=1;i<=n;i++)
    {
        ans=-1;
        for(int j=1;j<=seg[i].L;j++)
            for(int k=seg[i].R;k<=top;k++)
                ans=max(ans,G[j][k]);
        printf("%d\n",ans);
    }
	return 0;
}

/*
//BZOJ , 洛谷都能过 
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 410
#define INF 0x3f3f3f3f

using namespace std;

struct Segment
{
    int L,R;
}seg[MAXN*2];

int stack[MAXN*2],top=0,n;
int pre[MAXN][MAXN],suf[MAXN][MAXN],g[MAXN][MAXN];
int num[MAXN][MAXN];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&seg[i].L,&seg[i].R);
        seg[i].R+=seg[i].L; //!!!!
        stack[top++]=seg[i].L;
        stack[top++]=seg[i].R;
    }
    sort(stack,stack+top);
    top=unique(stack,stack+top)-stack;
    for(int i=1;i<=n;i++)
    {
        seg[i].L=lower_bound(stack,stack+top,seg[i].L)-stack;
        seg[i].R=lower_bound(stack,stack+top,seg[i].R)-stack;
    }
    for(int i=0;i<top;i++) //预处理出num[i][i]~num[i][top]
    {
        for(int j=1;j<=n;j++) //!!!!!
            if(seg[j].L>=i)
                num[i][seg[j].R]++;
        for(int j=i+1;j<top;j++) //!!!!!
            num[i][j]+=num[i][j-1];
    }
    memset(pre,~INF,sizeof(pre));
    memset(suf,~INF,sizeof(suf));
    pre[0][0]=0;
    suf[top-1][0]=0;
    for(int i=0;i<top;i++)
    {
        for(int j=0;j<=n;j++)
            if(pre[i][j]>~INF)
                pre[i][pre[i][j]]=max(pre[i][pre[i][j]],j);
        for(int j=n-1;j>=0;j--)
            pre[i][j]=max(pre[i][j],pre[i][j+1]);
        for(int j=0;j<=n;j++)
            for(int k=i+1;k<top;k++) //向后递推,[0,i]里给A放入j个区间,那么用[0,k]里在B中放入pre[i][j]个区间,在A中放入j+num[i][k]个区间的方案更新答案
                if(pre[i][j]>~INF)
                    pre[k][pre[i][j]]=max(pre[k][pre[i][j]],j+num[i][k]);
    }
    for(int i=top-1;i>=0;i--)
    {
        for(int j=0;j<=n;j++)
            if(suf[i][j]>~INF)
                suf[i][suf[i][j]]=max(suf[i][suf[i][j]],j);
        for(int j=n-1;j>=0;j--)
            suf[i][j]=max(suf[i][j],suf[i][j+1]);
        for(int j=0;j<=n;j++)
            for(int k=i-1;k>=0;k--) //向前递推,[i,INF)里给A放入j个区间,那么用[k,INF)里在B中放入suf[i][j]个区间,在A中放入j+num[k][i]个区间的方案来更新答案
                if(suf[i][j]>~INF)
                    suf[k][suf[i][j]]=max(suf[k][suf[i][j]],j+num[k][i]);
    }
    for(int i=0;i<top;i++) //求g[i][j]=必须使用[i,j]内的区间
        for(int j=i;j<top;j++)
        {
            g[i][j]=~INF;
            for(int x=0,y=n;x<=n;x++)
            {
                while(y>=0 && x+y > num[i][j]+pre[i][x]+suf[j][y]) y--; //x=[0,i]中B选择的区间个数,y=[j,INF)中B选择的区间个数
                if(y>=0) g[i][j]=max(g[i][j],x+y);
            }
        }
    int ans=0;
    for(int i=0;i<=n;i++)
        ans=max(ans,min(i,suf[0][i]));
    printf("%d\n",ans);
    for(int i=1;i<=n;i++) //!!!!
    {
        ans=0;
        for(int j=0;j<=seg[i].L;j++)
            for(int k=seg[i].R;k<top;k++)
                ans=max(ans,g[j][k]);
        printf("%d\n",ans);
    }
    //cout<<(~INF)<<endl;//负无穷大 
    return 0;
}
*/ 
/*
5 
8 2 
1 5 
5 3 
3 2 
5 3 
*/

/*
10
15 6
13 12
20 17
1 18
5 14
18 9
15 25
21 16
16 9
19 14


2
1
0
2
2
2
0
0
2
0
2









/*
200
2245677 6889928
598463 1250131
4624254 3174627
3504348 2942331
4320565 5223556
1340841 2998557
7826244 1545518
3754599 4526562
5638057 4358686
2209788 4037428
232358 5512177
2652842 5576425
4438992 2658453
4635494 4644989
1097240 2255095
4691195 1160450
6410437 4539207
1833322 3840732
4645008 7986055
4266108 3982209
2223528 1676678
3508563 4010408
1762626 689818
4115898 2432657
5488621 881237
7424583 1002486
2687274 6632758
7391815 715561
6505245 3018476
3086414 8343321
2131906 6480308
6543859 540897
6958703 6528618
691352 3059728
8269225 4392581
3066130 4768361
5991076 934697
3660455 1789678
3139659 6170042
7172722 1879702
3665743 6798102
3952357 7440384
2886189 1087330
2989912 7915370
4337297 3218412
7738837 7384457
2633277 5296088
274844 4723718
522457 2563098
5756119 7885240
7470062 4923782
1483939 4766354
1707042 4732589
6424016 8174792
4698779 6500054
5080051 4528610
3962827 5807725
3423313 6671533
6674461 3978015
6097416 168474
3561658 1030546
6910640 1774146
1985236 536306
5199047 130933
4017455 6738679
5418483 6701845
7129667 4500990
961748 388800
7455570 8095709
5211671 351634
840445 3123506
8272367 1487543
8046592 5662814
1665672 6974311
425397 5619459
7336628 3236152
401767 5044859
1561853 6892695
5925678 4123999
6323351 2452703
7049157 176916
3648518 4329093
7539879 2674467
1242493 4879537
7550583 6512678
4414139 1371638
4989319 7929807
5467962 2065887
993410 4875891
2375249 8187974
7149125 1520173
3961689 5438670
8359774 4037213
1544595 4208359
2854322 1016945
7906776 4752873
7221398 1994312
6055079 1730748
2954246 526416
6064936 4418003
5421432 5510589
5548924 3679464
391910 6359038
7800567 2410969
4780288 7364754
6584875 6009548
7086206 1994826
7712923 3776010
340092 760858
8307580 2878951
316966 5992203
6050681 3708499
539277 8326031
6658028 3462795
1962796 4460285
6134625 4378659
1649947 3813616
3489042 1209962
5745426 5666000
2915461 7668282
2393558 3506055
4316200 3094996
7570545 5303091
7965137 7931179
5095024 4179098
3254064 5177231
1473512 8232799
1420129 6610672
3858085 6880703
7474310 2172472
7709394 1433591
6517204 7464281
2951951 4549130
6423425 3022402
4431397 54284
6697178 7325924
2667162 7068786
2258216 6767725
1903749 2589344
5445426 8415164
1386331 4184419
2320986 5519513
6424735 7115521
6095452 5953632
2337149 1312740
7730170 806917
1252405 6730935
7243419 996157
7564892 2032174
6032029 622341
6860344 6790883
7809694 504578
1986619 7675253
3405956 2989269
6619457 3452777
1007570 3656542
160676 1801820
7228927 4168340
5223695 5547529
1946461 588843
4445137 1727992
1006099 5526990
5473936 1445819
7228004 968527
39888 7606779
3440753 6310041
5799711 7250509
5016423 7681249
5268842 3352488
7084082 1353252
3119193 1573428
6324938 5429102
2409594 1476485
4148035 7192523
5975566 7686259
7838065 6836480
2805635 7671972
4262440 6232480
3707887 2628484
2246793 8342935
2354838 2722734
4517421 3853614
7744136 5655756
2328044 6169892
5354308 6249212
4361442 2829063
6551614 5570108
2268825 4609345
1875455 6727931
735276 4506622
2729213 6592921
4786573 5908828
258262 7502165
4130562 7306177
1708480 2614303
5768531 1551375
3364437 103281
4604894 6833680
4120124 765299
3676867 7710232




52
4
52
23
48
18
52
52
15
36
52
52
11
36
23
52
52
52
52
23
22
52
28
52
45
52
52
7
52
52
8
4
52
52
52
52
15
43
52
8
52
12
16
52
7
27
52
13
52
52
39
52
52
48
52
25
29
16
9
52
52
52
52
52
52
18
31
52
52
52
52
52
52
52
2
52
52
52
2
43
50
52
16
52
52
52
52
27
34
52
4
52
16
52
52
52
52
52
44
52
44
31
34
39
52
26
52
52
52
52
52
52
44
0
52
51
45
52
52
38
7
52
30
52
52
29
8
2
7
13
52
52
52
27
52
52
52
7
4
52
31
52
11
52
44
52
52
6
52
52
43
52
52
4
52
52
52
52
52
29
52
52
46
39
52
16
9
40
28
30
52
52
50
52
18
43
52
7
18
52
4
52
22
52
4
31
34
52
40
3
52
7
26
11
18
52
39
52
23
52
12

*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值