51nod 1611 金牌赛事
被亮亮D飞啦!!QWQ
这题明明是最大权闭合子图+线段树优化构图好不好
被迫考虑DP,并且考虑f[i]表示到第i个位置的最大值(第i个位置可选可不选)
对于最终的答案,我们可以分割成一段一段的,也就是多段区间
枚举这个断点,断点以后的全选,前面的就通过继承得到,f[i]=f[j]-(sc[i]-sc[j])+(j+1到i这个区间中可以承办的比赛的价值和)
用数据结构优化的话,前面就可以nlogn了
而后面这一个,我们可以弄一个指针扫区间,看看当前是不是已经完全覆盖了,然后选取区间起始到这个区间的左界-1作为决策,后面的价值和就会加上这个区间的价值
区间修改也是线段树搞
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { int l,r,lc,rc;LL c,lazy; }tr[410000];int trlen; void bt(int l,int r) { int now=++trlen; tr[now].l=l;tr[now].r=r; tr[now].lc=tr[now].rc=-1; tr[now].c=0;tr[now].lazy=0; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); } } void change(int now,int l,int r,LL k) { if(tr[now].l==l&&tr[now].r==r) { tr[now].c+=k;tr[now].lazy+=k; return ; } int mid=(tr[now].l+tr[now].r)/2; int lc=tr[now].lc,rc=tr[now].rc; if(tr[now].lazy!=0) { tr[lc].c+=tr[now].lazy; tr[rc].c+=tr[now].lazy; tr[lc].lazy+=tr[now].lazy; tr[rc].lazy+=tr[now].lazy; tr[now].lazy=0; } if(r<=mid) change(lc,l,r,k); else if(mid+1<=l)change(rc,l,r,k); else change(lc,l,mid,k),change(rc,mid+1,r,k); tr[now].c=max(tr[lc].c,tr[rc].c); } LL getmax(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r)return tr[now].c; int mid=(tr[now].l+tr[now].r)/2; int lc=tr[now].lc,rc=tr[now].rc; if(tr[now].lazy!=0) { tr[lc].c+=tr[now].lazy; tr[rc].c+=tr[now].lazy; tr[lc].lazy+=tr[now].lazy; tr[rc].lazy+=tr[now].lazy; } if(r<=mid) return getmax(lc,l,r); else if(mid+1<=l)return getmax(rc,l,r); else return max(getmax(lc,l,mid),getmax(rc,mid+1,r)); } LL sc[210000]; struct game{int l,r;LL v;}g[210000]; bool cmp(game g1,game g2){return g1.r==g2.r?g1.l<g2.l:g1.r<g2.r;} LL f[210000]; int main() { int n,m; scanf("%d%d",&n,&m);sc[0]=0; for(int i=1;i<=n;i++) scanf("%lld",&sc[i]), sc[i]+=sc[i-1]; g[0].r=0; for(int i=1;i<=m;i++) scanf("%d%d%lld",&g[i].l,&g[i].r,&g[i].v); sort(g+1,g+m+1,cmp); trlen=0;bt(0,n); f[0]=0; for(int i=1,j=1;i<=n;i++) { while(j<=m&&g[j].r<=i)change(1,0,g[j].l-1,g[j].v),j++; f[i]=max(f[i-1],getmax(1,0,i-1)-sc[i]); change(1,i,i,f[i]+sc[i]); } printf("%lld\n",f[n]); return 0; }
pain and happy in the cruel world.