1 条题解

  • 0
    @ 2026-5-20 19:25:03

    solution

    观察到初始有疫情的所有城市会把所有初始没有疫情的 城市分割为若干个区间。

    怎么隔离

    对于一个区间 [l,r][l,r],有两种情况:

    l=1l=1r=nr=n

    则此时可以花费一天来将不为 11nn 的一个端点处打疫苗来将答案减少 rl+1r-l+1

    1<lr<n1<l\le r<n

    则此时又有两种情况:

    rl+12r-l+1\le 2

    此时只能将两个端点之一花费一天打疫苗,让另一个端点牺牲。

    rl+1>2r-l+1>2

    此时可以花费一天时间将其中一个端点打疫苗。

    由于在给一个端点打完疫苗后区间全部被感染所需的时间会由 (rl+1)÷2(r-l+1)\div 2 变为 rl+1r-l+1,所以由下文结论可得,最优策略为在下一天将另外一个端点往内一个城市处(原端点已被感染)打疫苗。

    我们可以将这种操作称为一次“隔离”。

    隔离什么

    在不打疫苗的情况下,对于一个区间 [l,r][l,r],其在时刻 tt 对答案的贡献有两种情况:

    l=1l=1r=nr=n

    trl+1t \le r-l+1 时,贡献为 11,否则贡献为 00

    1<lr<n1<l \le r<n

    t(rl+1)÷2t \le (r-l+1)\div 2 时,贡献为 22,当 t+0.5=(rl+1)÷2t+0.5=(r-l+1)\div 2 时,贡献为 11,否则贡献为 00

    观察可发现,在 rl+1r-l+1 值越小时,其贡献越容易变为 00。由于题目需求答案最小值,所以可以得出最优策略:优先隔离长度(既 rl+1r-l+1最大的区间,放弃长度较小的区间

    但是,这样做有一个小问题:l=1l=1r=nr=n 的区间的长度缩减速度更慢,所以应将所有区间按全部被感染所需时间从大到小排序,然后依次隔离。

    记得特判没有任何城市初始时被感染或全部城市初始时已被感染的情况。

    
    ```int curt=0; // 枚举当前的时刻
    		int curin=0;// 枚举当前考虑到的段
    		int ans=0;
    		while(curt*2<e[curin].t){
    			if(e[curin].l==0 || e[curin].r==n-1){ // 一头一尾
    				ans+= e[curin].r-e[curin].l+1 - curt;
    				++curt;
    			}
    			else{
    				if(curt*2+2>=e[curin].t){ // t+0.5<=(r-l+1)/2
    					++ans;
    					++curt;
    				}
    				else{ // t<=(r-l+1)/2
    					ans+=e[curin].r-e[curin].l+1 - curt*2-1;
    					curt+=2;
    				}
    			}
    			++curin;
    			if(curin>=m){
    				break;
    			}
    		}
    • 1

    信息

    ID
    1638
    时间
    2000ms
    内存
    512MiB
    难度
    9
    标签
    递交数
    175
    已通过
    18
    上传者