ICPC网络赛第一场----D Edge of Taixuan

题意:每次将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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值