• [Noip 2012] 借教室


    题面

        我们二分一下答案,看哪个是最后一个可以被满足的条件。

        每次二分得到mid之后,我们就把1~mid的条件用差分实现区间加,再把这个差分数组前缀和一下得到每个位置需要的教室数,判断一下就可以了。

        这里我加了一个小优化,每次修改差分数组都从上一次修改到的点开始修改(即吧差分数组的信息由 1~mid' 改为 1~mid),这样可以证明总的修改差分数组的时间是 O(M) 的。

        复杂度于是从 O( (N+M) * log M ) 降至 O( M + N*log M),再加之二分里那个O(N)的复杂度的常数要比原来没优化之前的O(M)的小得多(会提前返回0的情况),实测快了4倍不止。

    (注:图上的那个07-27是前年做的。。。。)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e6+5;
    
    inline int read(){
        int x=0; char ch=getchar();
        for(;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x;
    }
    
    int n,d[N],s[N],t[N];
    int r[N],m,R,L,mid,ans,pre;
    ll ad[N],now;
    
    inline bool can(){
    	now=0;
    	if(mid>pre) for(int i=pre+1;i<=mid;i++) ad[s[i]]+=(ll)d[i],ad[t[i]]-=(ll)d[i];
    	else for(int i=pre;i>mid;i--) ad[s[i]]-=(ll)d[i],ad[t[i]]+=(ll)d[i];
    	
    	for(int i=0;i<=n;i++,now+=ad[i]) if(now>r[i]) return 0;
    	return 1; 
    }
    
    int main(){
    	n=read(),R=m=read(),L=1;
    	for(int i=1;i<=n;i++) r[i]=read();
    	for(int i=1;i<=m;i++) d[i]=read(),s[i]=read(),t[i]=read()+1;
    	
    	for(;L<=R;pre=mid){
    		mid=L+R>>1;
    		if(can()) ans=mid,L=mid+1;
    		else R=mid-1;
    	}
    	
    	if(ans==m) puts("0");
    	else printf("-1
    %d
    ",ans+1);
    	
    	return 0;
    }
    

      

  • 相关阅读:
    407 Trapping Rain Water II 接雨水 II
    406 Queue Reconstruction by Height 根据身高重建队列
    405 Convert a Number to Hexadecimal 数字转换为十六进制数
    404 Sum of Left Leaves 左叶子之和
    403 Frog Jump 青蛙过河
    402 Remove K Digits 移掉K位数字
    401 Binary Watch 二进制手表
    400 Nth Digit 第N个数字
    398 Random Pick Index 随机数索引
    397 Integer Replacement 整数替换
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11283933.html
Copyright © 2020-2023  润新知