zoukankan      html  css  js  c++  java
  • [NOI2016] 区间

    不是很会做。
    大概是以前没有见过这种trick的原因。
    自己想到了线段树维护出现点数,但是不会统计答案。

    先分析一些东西:
    首先因为只有(m)个区间要被选,且答案贡献为(max - min),可以考虑尺取。
    感觉知道这个核心(trick)就能做了。
    从小到大加入,线段树随便维护一下。

    [NOI2016] 区间
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define N 500005
    
    struct P{ll l,r,len;}e[N];
    
    inline bool operator < (P a,P b){
    	return a.len < b.len;
    }
    
    ll b[N << 2];
    ll n,m;
    
    int ma[N << 3],lazy[N << 3];
    
    #define l(x) (x << 1)
    #define r(x) (x << 1 | 1)
    #define mid ((l + r) >> 1)
    
    inline void up(int u){
    	ma[u] = std::max(ma[l(u)],ma[r(u)]);
    }
    
    inline void down(int u){
    	ma[l(u)] += lazy[u];
    	ma[r(u)] += lazy[u];
    	lazy[l(u)] += lazy[u];
    	lazy[r(u)] += lazy[u];
    	lazy[u] = 0;
    }
    
    inline void add(int u,int l,int r,int tl,int tr,int p){
    //	std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<" "<<p<<std::endl;		
    	if(tl <= l && r <= tr){
    		ma[u] += p;
    		lazy[u] += p;
    //		std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<ma[u]<<" "<<p<<std::endl;		
    		return ;
    	}
    	down(u);
    	if(tl <= mid)
    	add(l(u),l,mid,tl,tr,p);
    	if(tr > mid)
    	add(r(u),mid + 1,r,tl,tr,p);
    	up(u);
    //	std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<ma[u]<<" "<<p<<std::endl;
    }
    
    ll ans = 0x3f3f3f3f;
    
    int main(){
    	scanf("%lld%lld",&n,&m);
    	for(int i = 1;i <= n;++i){
    		scanf("%lld%lld",&e[i].l,&e[i].r);
    		e[i].len = (e[i].r - e[i].l);
    //		b[++b[0]] = e[i].l - 1;
    		b[++b[0]] = e[i].l;
    		b[++b[0]] = e[i].r;
    //		b[++b[0]] = e[i].r + 1;
    	}
    	std::sort(b + 1,b + b[0] + 1);
    	std::sort(e + 1,e + n + 1);
    	b[0] = std::unique(b + 1,b + b[0] + 1) - b - 1;
    	ll l = 1;
    	ll r = 1;
    	e[n + 1].len = 0x3f3f3f3f; 
    //	for(int i = 1;i <= n;++i){
    ////		ll li = std::lower_bound(b + 1,b + b[0] + 1,e[i].l)- b;
    ////		ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[i].r)- b;
    //		std::cout<<e[i].l<<" "<<e[i].r<<" "<<e[i].len<<" "<<std::endl;
    //	}
    	ll li = std::lower_bound(b + 1,b + b[0] + 1,e[1].l) - b;
    	ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[1].r) - b;
    	add(1,1,b[0],li,ri,1);
    	while(l <= n && r <= n){
    		while(ma[1] >= m){
    			ll li = std::lower_bound(b + 1,b + b[0] + 1,e[l].l) - b;
    			ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[l].r) - b;
    			add(1,1,b[0],li,ri,-1);
    //			std::cout<<l<<" "<<r<<" "<<e[r].len<<" "<<e[l].len<<" "<<ma[1]<<std::endl;
    			ans = std::min(e[r].len - e[l].len,ans);			
    			++l;
    		}
    		while(ma[1] < m){
    			++r;
    			if(r > n)
    			break;
    			ll li = std::lower_bound(b + 1,b + b[0] + 1,e[r].l) - b;
    			ll ri = std::lower_bound(b + 1,b + b[0] + 1,e[r].r) - b;
    			add(1,1,b[0],li,ri,1);
    		}
    	}
    	if(ans < 0x3f3f3f3f)
    	std::cout<<ans<<std::endl;
    	else
    	puts("-1");
    }
    
  • 相关阅读:
    January 25th, 2018 Week 04th Thursday
    January 24th, 2018 Week 04th Wednesday
    January 23rd, 2018 Week 04th Tuesday
    January 22nd, 2018 Week 04th Monday
    January 21st, 2018 Week 3rd Sunday
    January 20th, 2018 Week 3rd Saturday
    January 19th, 2018 Week 3rd Friday
    January 18th, 2018 Week 03rd Thursday
    January 17th, 2018 Week 03rd Wednesday
    January 16th, 2018 Week 03rd Tuesday
  • 原文地址:https://www.cnblogs.com/dixiao/p/14891077.html
Copyright © 2011-2022 走看看