zoukankan      html  css  js  c++  java
  • #2007. 「SCOI2015」国旗计划

    好久没更过博了。。

    首先断环为链,因为线段互相不包含,所以对每个线段(i)可以找一个满足(r_jgeq l_i)(l_j)最小的线段,dp的时候(i)就会从(j)转移过来

    然后就j点到i点连一条边,形成了一个森林

    找方案可以枚举最右边的人(r),暴力向左跳,跳到一个(x)使得(l_x+mgeq r)就停下。r,x距离就是方案的人数,可以差分标记这些人

    就做完了

    注意断环为链的时候有些线段要copy一份

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    #define int ll
    typedef long long ll;
    il int gi(){
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if(ch=='-')f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    struct yyb{int l,r,i,o;}s[400010],sl[400010],sr[400010];
    il bool cmpl(const yyb&a,const yyb&b){return a.l<b.l;}
    il bool cmpr(const yyb&a,const yyb&b){return a.r<b.r;}
    int fir[400010],dis[400010],nxt[400010],id;
    il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    il bool operator<(const yyb&a,const yyb&b){return a.l<b.l;}
    std::multiset<yyb>S;
    bool yes[400010];
    int st[19][400010],dep[400010],c[400010];
    il vd dfs(int x){for(int i=fir[x];i;i=nxt[i])dep[dis[i]]=dep[x]+1,st[0][dis[i]]=x,dfs(dis[i]);}
    il vd dfs2(int x){for(int i=fir[x];i;i=nxt[i])dfs2(dis[i]),c[x]+=c[dis[i]];}
    int ans[400010];
    bool ANS[200010];
    signed main(){
    	int n=gi(),m=gi(),N=0;
    	for(int i=1;i<=n;++i){
    		++N;
    		s[N].l=gi(),s[N].r=gi();s[N].i=N;s[N].o=i;
    		if(s[N].l>s[N].r)s[N].r+=m,sl[N]=sr[N]=s[N];
    		else{
    			sl[N]=sr[N]=s[N];
    			++N,s[N]=s[N-1];s[N].i=N;
    			s[N].l+=m,s[N].r+=m;
    			sl[N]=sr[N]=s[N];
    		}
    	}
    	std::sort(sl+1,sl+N+1,cmpl);
    	std::sort(sr+1,sr+N+1,cmpr);
    	for(int i=1;i<=N;++i)S.insert(s[i]);
    	int p=1;
    	for(int i=1;i<=N;++i){
    		while(p<=N&&sr[p].r<sl[i].l)S.erase(S.find(sr[p])),++p;
    		if(!S.empty()&&S.begin()->l<sl[i].l)link(S.begin()->i,sl[i].i);
    		else yes[sl[i].i]=1;
    	}
    	for(int i=1;i<=N;++i)if(yes[i])dep[i]=1,dfs(i);
    	for(int i=1;i<19;++i)
    		for(int j=1;j<=N;++j)
    			st[i][j]=st[i-1][st[i-1][j]];
    	int _ans=1e9;
    	for(int i=1;i<=N;++i){
    		ans[i]=i;
    		for(int j=18;~j;--j)if(st[j][ans[i]]&&s[st[j][ans[i]]].l+m>s[i].r)ans[i]=st[j][ans[i]];
    		if(st[0][ans[i]])_ans=std::min(_ans,dep[i]-dep[ans[i]]+2);
    	}
    	for(int i=1;i<=N;++i)
    		if(st[0][ans[i]]&&dep[i]-dep[ans[i]]+2==_ans)
    			++c[i],--c[st[1][ans[i]]];
    	for(int i=1;i<=N;++i)if(yes[i])dfs2(i);
    	for(int i=1;i<=N;++i)if(c[i])ANS[s[i].o]=1;
    	for(int i=1;i<=n;++i)printf("%lld ",_ans+1-ANS[i]);
    	return 0;
    }
    
  • 相关阅读:
    CF11C How Many Squares?
    CF3D Least Cost Bracket Sequence
    P4106 [HEOI2014]逻辑翻译
    吉大第二届青云杯复赛第6题
    2017六省联考部分题目整理【期末考试,寿司餐厅,组合数问题,分手是祝愿】
    CF578D LCS Again
    P5072 [Ynoi2015]盼君勿忘
    P3232 [HNOI2013]游走
    P6154 游走
    P4648 [IOI2007] pairs 动物对数
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10022578.html
Copyright © 2011-2022 走看看