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;
    }
    
  • 相关阅读:
    如何将网格式报表打印成其它样式
    拥有与实力不相称的脾气是种灾难——北漂18年(23)
    8.8.1 Optimizing Queries with EXPLAIN
    mysql 没有rowid 怎么实现根据rowid回表呢?
    secondary index
    8.5.5 Bulk Data Loading for InnoDB Tables 批量数据加载
    mysql 中key 指的是索引
    8.5.4 Optimizing InnoDB Redo Logging 优化InnoDB Redo 日志
    8.5.3 Optimizing InnoDB Read-Only Transactions 优化InnoDB 只读事务
    8.5.1 Optimizing Storage Layout for InnoDB Tables InnoDB表的存储布局优化
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/11122489.html
Copyright © 2011-2022 走看看