题意:方便起见,丽娃河可以看成是从 1 到 n 的一条数轴。为了美观,路灯只能安装在整数点上,每个整数点只能安装一盏路灯。经专业勘测,有 m 个区间特别容易发生事故,所以至少要安装一定数量的路灯,请问至少还要安装多少路灯。
思路:按右端点排序,然后缺的路灯尽量往后放,这题数据很弱,暴力也可以过。。。比赛的时候智障了,-1的时候没有输出Case #,wa了半天。
暴力代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e3+5;
struct node
{
int l, r, cnt;
bool operator < (const node &a) const
{
return r < a.r;
}
}a[maxn];
bool have[maxn];
int main(void)
{
int t, n, m, k, ca = 1;
cin >> t;
while(t--)
{
memset(have, 0, sizeof(have));
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= k; i++)
{
int tmp;
scanf("%d", &tmp);
have[tmp] = 1;
}
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].cnt);
sort(a+1, a+1+m);
int ans = 0;
bool ok = 1;
for(int i = 1; i <= m; i++)
{
int l = a[i].l;
int r = a[i].r;
int cnt = a[i].cnt;
if(cnt > r-l+1) ok = 0;
if(!ok) break;
int cur = 0;
for(int j = l; j <= r; j++)
if(have[j]) cur++;
int need = cnt-cur;
ans += max(0, need);
for(int j = r; j >= l && need > 0; j--)
{
if(!have[j])
{
have[j] = 1;
need--;
}
}
}
if(!ok) printf("Case %d: -1\n", ca++);
else printf("Case %d: %d\n", ca++, ans);
}
return 0;
}
线段树代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e3+5;
int sum[maxn*4], lazy[maxn*4], set[maxn*4], n, q;
void pushup(int root, int l, int r)
{
sum[root] = sum[root*2]+sum[root*2+1];
}
void pushdown(int root, int l, int r)
{
int mid = (l+r)/2;
if(set[root] != -1)
{
lazy[root*2] = lazy[root*2+1] = 0;
set[root*2] = set[root*2+1] = set[root];
sum[root*2] = set[root]*(mid-l+1);
sum[root*2+1] = set[root]*(r-mid);
set[root] = -1;
}
if(lazy[root])
{
lazy[root*2] += lazy[root];
lazy[root*2+1] += lazy[root];
sum[root*2] += lazy[root]*(mid-l+1);
sum[root*2+1] += lazy[root]*(r-mid);
lazy[root] = 0;
}
}
void Set(int root, int l, int r, int i, int j, int val)
{
if(i <= l && j >= r)
{
set[root] = val;
lazy[root] = 0;
sum[root] = val*(r-l+1);
return ;
}
pushdown(root, l, r);
int mid = (l+r)/2;
if(i <= mid) Set(root*2, l, mid, i, j, val);
if(j > mid) Set(root*2+1, mid+1, r, i, j, val);
pushup(root, l, r);
}
void update(int root, int l, int r, int i, int j, int val)
{
if(i <= l && j >= r)
{
lazy[root] += val;
sum[root] += val*(r-l+1);
return ;
}
pushdown(root, l, r);
int mid = (l+r)/2;
if(i <= mid) update(root*2, l, mid, i, j, val);
if(j > mid) update(root*2+1, mid+1, r, i, j, val);
pushup(root, l, r);
}
int query(int root, int l, int r, int i, int j)
{
if(i <= l && j >= r) return sum[root];
pushdown(root, l, r);
int mid = (l+r)/2;
int res = 0;
if(i <= mid) res += query(root*2, l, mid, i, j);
if(j > mid) res += query(root*2+1, mid+1, r, i, j);
pushup(root, l, r);
return res;
}
struct node
{
int l, r, t;
bool operator < (const node &a) const
{
return r < a.r;
}
}a[maxn];
int main(void)
{
int t, n, m, k, ca = 1;
cin >> t;
while(t--)
{
memset(lazy, 0, sizeof(lazy));
memset(sum, 0, sizeof(sum));
memset(set, -1, sizeof(set));
scanf("%d%d%d", &n, &m, &k);
bool ok = 1;
for(int i = 1; i <= k; i++)
{
int t;
scanf("%d", &t);
update(1, 1, n, t, t, 1);
}
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].t);
sort(a+1, a+1+m);
int ans = 0;
for(int i = 1; i <= m; i++)
{
int l = a[i].l;
int r = a[i].r;
int num = a[i].t;
if(num > r-l+1) ok = 0;
if(!ok) continue;
int cur = query(1, 1, n, l, r);
int need = num-cur;
ans += max(0, need);
if(need <= 0) continue;
int li = 1, ri = r, dis;
while(li <= ri)
{
int mid = (li+ri)/2;
int can = r-mid+1-query(1, 1, n, mid, r);
if(can >= need) li = mid+1, dis = mid;
else ri = mid-1;
}
Set(1, 1, n, dis, r, 1);
}
if(!ok) printf("Case %d: -1\n", ca++);
else printf("Case %d: %d\n", ca++, ans);
}
return 0;
}