题意:每次将l到r范围内的所有点加一条长度为val的值(可以重边)
然后删掉一部分边,使得1到n联通,问删除的边和最大
思路:区间覆盖问题,首先判断能否到达终点,其次对边先进行降序排序,对于修改区间l到r的操作可以认为是修改l到r-1的值,每个点的值代表的是这个点到后一个点的距离,然后用所有边的和减去最终得到的和即为答案
代码:
#include<bits/stdc++.h>
#define x first
#define y second
#define mm(x) memset((x),sizeof((x)),0)
#define ll long long
using namespace std;
const int N=1e5+10;
const int INF=0x3f3f3f3f;
struct node{
int l,r;
ll w;
int lazy;
}st[N*4];
struct ed{
int l,r,w;
bool operator<(const ed&m) const
{
return w>m.w;
}
}ed[N];
typedef pair<int,int> pii;
pii ad[N];
void pushup(int u)
{
st[u].w=st[u<<1].w+st[u<<1|1].w;
}
void pushdown(int u)
{
node &r=st[u],&lr=st[u<<1],&rr=st[u<<1|1];
if(r.lazy)
{
lr.lazy=r.lazy,lr.w=1ll*(lr.r-lr.l+1)*lr.lazy;
rr.lazy=r.lazy,rr.w=1ll*(rr.r-rr.l+1)*rr.lazy;
r.lazy=0;
}
}
void build(int u,int l,int r)
{
st[u]={l,r,0,INF};
if(l==r) return ;
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,int val)
{
if(st[u].l>=l&&st[u].r<=r) st[u].lazy=val,st[u].w=1ll*(st[u].r-st[u].l+1)*st[u].lazy;
else
{
pushdown(u);
int mid=st[u].r+st[u].l>>1;
if(l<=mid) modify(u<<1,l,r,val);
if(r>mid) modify(u<<1|1,l,r,val);
pushup(u);
}
}
ll query(int u,int l,int r)
{
if(st[u].l>=l&&st[u].r<=r) return st[u].w;
else
{
pushdown(u);
int mid=st[u].l+st[u].r>>1;
ll ans=0;
if(l<=mid) ans+=query(u<<1,l,r);
if(r>mid) ans+=query(u<<1|1,l,r);
return ans;
}
}
int main()
{
int t;
scanf("%d",&t);
int cnt=1;
while(t--)
{
printf("Case #%d: ",cnt++);
mm(st),mm(ed),mm(ad);
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n-1);
int all=0;
ll res=0;
while(m--)
{
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
ad[all]={l,r};
ed[all]={l,r,val};
all++;
res+=1ll*(r-l+1)*(r-l)/2*val;
}
sort(ad,ad+all),sort(ed,ed+all);
int r=1;
bool f=true;
for(int i=0;i<all;i++)
{
if(ad[i].x>r) {f=false;break;}
r=max(r,ad[i].y);
}
if(r!=n) f=false;
if(!f) printf("Gotta prepare a lesson\n");
else
{
for(int i=0;i<all;i++)
{
modify(1,ed[i].l,ed[i].r-1,ed[i].w);
}
printf("%lld\n",res-query(1,1,n-1));
}
/*if(cnt!=t) puts("");*/
}
return 0;
}