zoukankan      html  css  js  c++  java
  • CF1012F Passports

    http://codeforces.com/problemset/problem/1012/F

    题解

    考虑(p=1)的情况。

    我们可以把题意理解成平面上有一些线段,你需要给每条线段分配一个长度给定的预备线段,使得预备线段要在它所属的线段前面,并且所有线段不能相交。

    因为我们只需要弄出一组解来,所以我们可以直接设(dp[s])表示(s)集合内的所有旅行都办好了签证,最后拿到护照的最小时间。

    于是我们发现(p=2)时我们只需要把它们分成两组,每组都满足条件就行了,并且需要满足每次办理签证的当前不能再某次旅行途中。

    所以对于(p=2)的情况,我们还是按照上面去(dp),最后枚举划分就好了。

    然后考虑怎么(dp)

    我们可以直接枚举一个状态,然后枚举下一次办理那个国家的签证,然后判断一下就行。

    如何判断新加入一个国家时需要的时间,我们设上一次的时间为(last)

    我们可以把所有初始,的线段排序,然后我们从前往后扫描每个线段,当当前时间与这个线段冲突时就把时间往后推。

    然后发现这个是有单调性的,于是可以把所有要转移的按照签证时间排序,双指针即可。

    代码

    #include<bits/stdc++.h>
    #define N 25
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    int n,p;
    int bit[1<<23];
    int ansl[N];
    ll ansr[N];
    int tot,b[N],tot1,c[N];
    ll dp[1<<23],tag[1<<23];
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    struct node{
    	int l,r,t,id;
    	inline bool operator <(const node &b)const{
    		return l<b.l;
    	}
    }a[N];
    inline bool cmp(int x,int y){
    	return a[x].t<a[y].t;
    }
    void dfs(int s,int tg){
    	if(!s)return;
    	int x=tag[s];
    	ansr[a[x].id]=dp[s]-a[x].t;
    	ansl[a[x].id]=tg;
    	dfs(s-(1<<x-1),tg);
    }
    int main(){
      n=rd();p=rd();
      for(int i=1;i<=n;++i){
      	a[i].l=rd();
      	int x=rd();
      	a[i].r=a[i].l+x-1;
      	a[i].t=rd();
      	a[i].id=i;
      }
      sort(a+1,a+n+1);
      memset(dp,0x3f,sizeof(dp));
      for(int i=1;i<=n;++i)bit[1<<i-1]=i;
      int maxn=(1<<n);
      dp[0]=1;
      for(int i=0;i<maxn;++i)if(dp[i]<1e15){
      	tot=tot1=0;
      	for(int j=1;j<=n;++j)if(!(i&(1<<j-1)))b[++tot]=j;else c[++tot1]=j;
      	sort(b+1,b+tot+1,cmp);
        int p1=1,p2=1;
        ll last=dp[i];
        for(int j=1;j<=tot;++j){
          int now=b[j];
          while(1){
          	bool tg=0;
            if(last>=a[p1].l&&p1<=n){
          	  last=max(last,(ll)a[p1].r+1);
          	  p1++;tg=1;
            }
            while(last>a[c[p2]].l&&p2<tot1)p2++;
            if(last<=a[c[p2]].l&&p2<=tot1){
          	  int xx=c[p2];
              if(a[xx].l<=last+a[now].t)last=max(last,(ll)a[xx].r+1),p2++,tg=1;
            }
            if(!tg)break;
          }
          int s=i^(1<<now-1);
          if(last+a[now].t<a[now].l&&last+a[now].t<dp[s])dp[s]=last+a[now].t,tag[s]=now;
        }
      }
      if(p==1){
        if(dp[maxn-1]<1e15){
        	dfs(maxn-1,1);
        	puts("YES");
        	for(int j=1;j<=n;++j)cout<<ansl[j]<<" "<<ansr[j]<<"
    ";
        }
        else puts("NO");
      }
      else{
      	for(int i=0;i<maxn;++i)if(dp[i]<1e15&&dp[maxn-1-i]<1e15){
            dfs(i,1);dfs(maxn-1-i,2);
            puts("YES");
            for(int j=1;j<=n;++j)cout<<ansl[j]<<" "<<ansr[j]<<"
    ";
            return 0;
      	}
      	puts("NO");
      }
      return 0;
    }
    
  • 相关阅读:
    CTF -攻防世界-crypto新手区(5~11)
    CTF密码学常见加密解密总结
    CTF -攻防世界-crypto新手区(1~4)
    跨域问题解决
    npm使用记录
    dva控制元素动态消失隐藏
    maven安装记录
    postgreSQL记录
    关于System.__ComObject一些问题
    论文中表格跨页处理
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/11122489.html
Copyright © 2011-2022 走看看