AT_dp_w Intervals题解

题目描述

考虑一个长度为 N、仅由 0 和 1 组成的字符串。该字符串的分数按照如下方式计算:

  • 对于每个 i(1≤i≤M),如果从第 li​ 个字符到第 ri​ 个字符之间至少包含一个 1,则将 ai​ 加到分数上。

请你求出字符串分数的最大值。

输入格式

输入以如下格式从标准输入读入。

N M l1​ r1​ a1​ l2​ r2​ a2​ … lM​ rM​ aM​

输出格式

输出字符串分数的最大值。

显示翻译

题意翻译

输入输出样例

输入 #1复制

5 3
1 3 10
2 4 -10
3 5 10

输出 #1复制

20

输入 #2复制

3 4
1 3 100
1 1 -10
2 2 -20
3 3 -30

输出 #2复制

90

输入 #3复制

1 1
1 1 -10

输出 #3复制

0

输入 #4复制

1 5
1 1 1000000000
1 1 1000000000
1 1 1000000000
1 1 1000000000
1 1 1000000000

输出 #4复制

5000000000

输入 #5复制

6 8
5 5 3
1 1 10
1 6 -8
3 6 5
3 4 9
5 5 -2
1 3 -6
4 6 -7

输出 #5复制

10

说明/提示

限制条件

  • 所有输入均为整数。
  • 1≤N≤2×105
  • 1≤M≤2×105
  • 1≤li​≤ri​≤N
  • ∣ai​∣≤109

样例解释 1

10001 的分数为 a1​+a3​=10+10=20。

样例解释 2

100 的分数为 a1​+a2​=100+(−10)=90。

样例解释 3

0 的分数为 0。

样例解释 4

答案可能超出 32 位整数范围。

样例解释 5

例如,101000 的分数为 a2​+a3​+a4​+a5​+a7​=10+(−8)+5+9+(−6)=10。

由 ChatGPT 4.1 翻译

思路

线段树优化DP。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long n,m,b[1000006],te[4000006],lz[4000006],u,ll,rr;
struct one{
    long long l,r,v;
}a[200005];
bool cmp(one a1,one b1){
    return a1.r<b1.r;
}
void alz(int a1,long long v){
	te[a1]+=v;
	lz[a1]+=v;
}
void dow(int a1){
	alz(a1*2,lz[a1]);
	alz(a1*2+1,lz[a1]);
	lz[a1]=0;
}//a1下发标记至儿子
void ci(int a1,int l,int r,int x,int y,long long v){
	if(l>=x&&r<=y){
		te[a1]+=v;
        lz[a1]+=v;
		return ;
	}
	int mid=(l+r)/2;
	dow(a1);
	if(x<=mid){
		ci(a1*2,l,mid,x,y,v);
	}
	if(mid+1<=y){
		ci(a1*2+1,mid+1,r,x,y,v);
	}
	te[a1]=max(te[a1*2],te[a1*2+1]);
	return ;
}//x~y区间加v至l~r区间a1点
int main(){
	cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a[i].l>>a[i].r>>a[i].v;
    }
    sort(a+1,a+m+1,cmp);
    for(int i=1,j=1;i<=n;i++){
        ci(1,1,n,i,i,max(0ll,te[1]));
        while(a[j].r==i&&j<=m){
            ci(1,1,n,a[j].l,a[j].r,a[j].v);
            j++;
        }
    }
    cout<<max(0ll,te[1])<<endl;
	return 0;
}

posted @ 2025-10-23 10:39  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源