題目大意:
給定一些區間[ai,bi]以及一個數量wi,找到一個幾何V,要求區間[ai,bi]在集合V中至少包含wi個元素,求V中至少應包含多少個元素。
題解:
嗯,這個題目只要把每個區間的長度求出來然後減去重合的部分就可以了,但是今天學習了一種新的算法——拆分約束,解題很方便。
給定dis[i]表示第I個點到源點的距離,根據已知條件有:
dis[ai]<=dis[bi]-w[i]
dis[i+1]<=dis[i]+1;
dis[i]<=dis[i+1];
然後,每次進行更新(類似SPFA算法),直到再也找不到邊可以更新了,答案就是源點到終點的距離。
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int n,s[50001],dis[50001],e[50001],w[50001],start,end,i,j,k;
int main(){
while (scanf("%d",&n)!=EOF){
for (i=0;i<n;i++){
scanf("%d%d%d",&s[i],&e[i],&w[i]);
e[i]+=1;
if (start>s[i]) start=s[i];
if (end<e[i]) end=e[i];
}
memset(dis,0,sizeof(dis));
int tag=1;
while (tag){
tag=0;
for (i=0;i<n;i++)
if (dis[s[i]]>dis[e[i]]-w[i])
dis[s[i]]=dis[e[i]]-w[i],tag=1;
for (i=start;i<end;i++)
if (dis[i+1]>dis[i]+1)
dis[i+1]=dis[i]+1,tag=1;
for (i=end-1;i>=start;i--)
if (dis[i]>dis[i+1])
dis[i]=dis[i+1],tag=1;
}
printf("%d\n",dis[end]-dis[start]);
}
return 0;
}