洛谷 SP116 INTERVAL - Intervals
洛谷 SP116 INTERVAL - Intervals
节选自。如果您想学习差分约束的话不妨看看~
Problem
从\(0\sim50000\)选出最少的数,使每个区间至少有\(c\)个数被选。
Solution
这是求最小值,所以将所有的不等式转换成\(\ge\)的形式。
类似于P1250 种树的思想,考虑如何将题目中的
设\(sum[x]\)是前缀和:
对于每一个约束条件,可以看成\(sum[b_i]-sum[a_i-1]\ge c_i\).
由于每一个数只能选择一次,\(0\le sum_x-sum_{x-1}\le1\).
注意这里下标是从\(0\)开始的,所以就全部\(+1\)就好。
最后,多测不清空,抱玲两行泪。
Code
/**************************************************************
* Problem: SP116
* Author: Vanilla_chan
* Date: 20210330
* E-Mail: Vanilla_chan@outlook.com
**************************************************************/
//预编译部分已略
#define N 500010
int n,m,s;
int head[N],ver[N<<1],cnt[N],nxt[N<<1],w[N<<1],dis[N],book[N];
int tot;
void insert(int x,int y,int z)
{
nxt[++tot]=head[x];
head[x]=tot;
w[tot]=z;
ver[tot]=y;
}
struct node
{
int x,dis;
node(int xx,int vv)
{
x=xx,dis=vv;
}
};
queueq;
LL ans;
int t;
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
t=read();
while(t--)
{
tot=0;
memset(head,0,sizeof(head));
memset(nxt,0,sizeof(nxt));
memset(dis,0,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(w,0,sizeof(w));
memset(book,0,sizeof(book));
memset(ver,0,sizeof(ver));
n=0;
m=read();
for(int i=1,a,b,c;i<=m;i++)
{
a=read();
b=read();
c=read();
n=max(n,max(a,b));
insert(a,b+1,c);
}
s=n+2;
for(int i=1;i<=n+1;i++)
{
dis[i]=-1;
insert(s,i,0);
insert(i-1,i,0);
insert(i,i-1,-1);
}
int x;
q.push(node(s,0));
while(!q.empty())
{
x=q.front().x;
q.pop();
book[x]=0;
for(int i=head[x],v;i;i=nxt[i])
{
v=ver[i];
if(dis[v]n)
{
cout<<"-1";
return 0;
}
q.push(node(v,dis[v])),book[v]=1,cnt[v]++;
}
}
}
}
cout<