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;
}

浙公网安备 33010602011771号