【gym102394A】Artful Paintings(差分约束系统,二分)

题意:给定一个长为n的序列,每个位置可以选择取或不取,要求构造方案使得:

1.对于前M1个约束,区间【L,R】内取的数量必须严格不少于K

2.对于后M2个约束,区间【L,R】外取的数量必须严格不少于K

3.满足所有M1+M2个约束的前提下使得取的个数最少,输出最少取的个数

n,M1,M2<=3e3

思路:做法一:

 

 特殊的SPFA判负环的技巧见https://www.cnblogs.com/myx12345/p/6212893.html

大致说来就是用栈和初始置0两个地方

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 typedef pair<ll,ll>P;
 12 #define N  500010
 13 #define M  1000000
 14 #define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 #define fors(i) for(auto i:e[x]) if(i!=p)
 29 
 30 const int MOD=1e9+7,inv2=(MOD+1)/2;
 31       double eps=1e-6;
 32       int dx[4]={-1,1,0,0};
 33       int dy[4]={0,0,-1,1};
 34 
 35 struct edge
 36 {
 37     int x,y,z;
 38 }a[N],b[N];
 39 
 40 int head[N],vet[N],nxt[N],inq[N],dis[N],stk[N],len[N],t[N],
 41     n,m1,m2,tot;
 42 
 43 int read()
 44 {
 45    int v=0,f=1;
 46    char c=getchar();
 47    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 48    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 49    return v*f;
 50 }
 51 
 52 ll readll()
 53 {
 54    ll v=0,f=1;
 55    char c=getchar();
 56    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 57    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 58    return v*f;
 59 }
 60 
 61 void add(int a,int b,int c)
 62 {
 63     nxt[++tot]=head[a];
 64     vet[tot]=b;
 65     len[tot]=c;
 66     head[a]=tot;
 67 }
 68 
 69 void build(int k)
 70 {
 71     //printf("k=%d\n",k);
 72     tot=0;
 73     rep(i,0,n) head[i]=0;
 74     rep(i,0,n-1)
 75     {
 76         add(i+1,i,0);
 77         add(i,i+1,1);
 78     }
 79     rep(i,1,m1) add(a[i].y,a[i].x-1,-a[i].z);
 80     rep(i,1,m2) add(b[i].x-1,b[i].y,k-b[i].z);
 81     add(0,n,k);
 82     add(n,0,-k);
 83 }
 84 
 85 int isok()
 86 {
 87     rep(i,0,n) inq[i]=dis[i]=t[i]=0;
 88     int top=0;
 89     rep(i,0,n)
 90     {
 91         top++;
 92         stk[top]=i;
 93         inq[i]=1;
 94         t[0]=i;
 95     }
 96     while(top)
 97     {
 98         int u=stk[top];
 99         top--;
100         inq[u]=0;
101         int e=head[u];
102         while(e)
103         {
104             int v=vet[e];
105             if(dis[u]+len[e]<dis[v])
106             {
107                 dis[v]=dis[u]+len[e];
108                 if(!inq[v])
109                 {
110                     top++;
111                     stk[top]=v;
112                     inq[v]=1;
113                     t[v]++;
114                     if(t[v]==n+2) return 0;
115                 }
116             }
117             e=nxt[e];
118         }
119     }
120     return 1;
121 }
122 
123 void solve()
124 {
125     n=read(),m1=read(),m2=read();
126     rep(i,1,m1) a[i].x=read(),a[i].y=read(),a[i].z=read();
127     rep(i,1,m2) b[i].x=read(),b[i].y=read(),b[i].z=read();
128     int l=0,r=n,last=n;
129     while(l<=r)
130     {
131         int mid=(l+r)>>1;
132         build(mid);
133         if(isok()){last=mid; r=mid-1;}
134          else l=mid+1;
135     }
136     printf("%d\n",last);
137 }
138 
139 int main()
140 {
141     //freopen("1.in","r",stdin);
142     int cas=read();
143     while(cas--) solve();
144     return 0;
145 }

 

posted on 2019-11-11 16:13  myx12345  阅读(388)  评论(0编辑  收藏  举报

导航