280D k-Maximum Subsequence Sum(區間最大k段和)(線段樹 + 最大子段和 + 區間修改 + 區間查詢 + 單點修改)
題目
題意
給定個數的序列,定義兩個操作
把序列第k個數的值變為val
詢問在區間 中,選取 段不相交的子區間,使得這 段子區間的和最大,其中。
思路
首先這裡講了如何解決 的情況,即用線段樹維護並進行合併
然後考慮如何取k段,我們只需要去給定區間取 次區間最大子段和,累加答案後,對取出的區間做區間取反操作。而當所取的區間最大子段和小於 的時候,則跳出不計
做法的正確性可以從貪心或者費用流的思想上證明
之後再進行單點修改就行了
那麼實現的就在維護的是 這三個值的時候,如何進行取反操作,如何在找出 的同時記錄下,對應的哪一段區間。(這三個變數的含義見區間最大子段和部分)
而取反實際上就是將最大子段和以及最小子段和進行了交換,而我們只需要同時維護最大子段和最小子段和,記錄下對應的區間資訊,在取反操作時對調就可以了。而又由於我們的 是用 來維護的,所有後兩者的區間資訊也需要記錄
於是就有了這麼一個維護了18個值的線段樹…
區間和 區間的左右邊界
最小子段和 最小子段和的左右邊界
最大字首和 最大字首和的右邊界
最小字首和 最小字首和的右邊界
最大字尾和 最大字尾和的左邊界
最小字尾和 最小字尾和的左邊界
區間取反標記
然後將區間合併更新所有的最佳情況函式化為了
又由於使用了 ,所以 需要在 前記錄一下並賦值
其他的就是基本的線段樹的操作了
程式碼
#include <bits/stdc++.h>
using namespace std;
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define pd(n) printf("%d\n", (n))
#define pdd(n,m) printf("%d %d", n, m)
#define pld(n) printf("%lld\n", n)
#define pldd(n,m) printf("%lld %lld\n", n, m)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define mm(a,n) memset(a, n, sizeof(a))
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define mk make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const ll mod = 1000000007;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+5;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
template<typename T>inline void read(T &x){
T f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(x=0;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
x*=f;
}
// head
struct Node {
int l, r;
int sum, tag;
int maxs, maxl, maxr;
int maxsl, maxsr, minsl, minsr;
int maxlp, maxrp, minlp, minrp;
int mins, minl, minr;
} tree[maxn<<2];
int num[maxn];
Node merged(Node ls, Node rs){
Node ret;
ret.sum = ls.sum + rs.sum;
ret.l = ls.l;
ret.r = rs.r;
ret.tag = 0;
if(ls.maxs > rs.maxs){
ret.maxs = ls.maxs;
ret.maxsl = ls.maxsl;
ret.maxsr = ls.maxsr;
}
else {
ret.maxs = rs.maxs;
ret.maxsl = rs.maxsl;
ret.maxsr = rs.maxsr;
}
if(ret.maxs < ls.maxr + rs.maxl) {
ret.maxs = ls.maxr + rs.maxl;
ret.maxsl = ls.maxrp;
ret.maxsr = rs.maxlp;
}
if(ls.maxl > ls.sum + rs.maxl){
ret.maxl = ls.maxl;
ret.maxlp = ls.maxlp;
}
else{
ret.maxl = ls.sum + rs.maxl;
ret.maxlp = rs.maxlp;
}
if(rs.maxr > rs.sum + ls.maxr){
ret.maxr = rs.maxr;
ret.maxrp = rs.maxrp;
}
else {
ret.maxr = rs.sum + ls.maxr;
ret.maxrp = ls.maxrp;
}
if(ls.mins < rs.mins){
ret.mins = ls.mins;
ret.minsl = ls.minsl;
ret.minsr = ls.minsr;
}
else {
ret.mins = rs.mins;
ret.minsl = rs.minsl;
ret.minsr = rs.minsr;
}
if(ret.mins > ls.minr + rs.minl) {
ret.mins = ls.minr + rs.minl;
ret.minsl = ls.minrp;
ret.minsr = rs.minlp;
}
if(ls.minl < ls.sum + rs.minl){
ret.minl = ls.minl;
ret.minlp = ls.minlp;
}
else{
ret.minl = ls.sum + rs.minl;
ret.minlp = rs.minlp;
}
if(rs.minr < rs.sum + ls.minr){
ret.minr = rs.minr;
ret.minrp = rs.minrp;
}
else {
ret.minr = rs.sum + ls.minr;
ret.minrp = ls.minrp;
}
return ret;
}
void inv(int i){
tree[i].sum = -tree[i].sum;
tree[i].tag ^= 1;
swap(tree[i].maxs, tree[i].mins);
swap(tree[i].maxsl, tree[i].minsl);
swap(tree[i].maxsr, tree[i].minsr);
tree[i].maxs = -tree[i].maxs; tree[i].mins = -tree[i].mins;
swap(tree[i].maxl, tree[i].minl);
swap(tree[i].maxlp, tree[i].minlp);
tree[i].maxl = -tree[i].maxl
相關推薦
280D k-Maximum Subsequence Sum(區間最大k段和)(線段樹 + 最大子段和 + 區間修改 + 區間查詢 + 單點修改)
題目
題意
給定nn個數的序列,定義兩個操作
⋅0kval⋅0kval 把序列第k個數的值變為val
⋅1lrk⋅1lrk 詢問在區間 Al⋯ArAl⋯Ar 中,選取 mm 段不相交的子區間,使得這 mm 段子區間的和最大,其中0≤m≤k0≤m≤k。
【BZOJ3638】Cf172 k-Maximum Subsequence Sum 線段樹區間合並(模擬費用流)
font uil sin upper sample dex else name etc 【BZOJ3638】Cf172 k-Maximum Subsequence Sum
Description
給一列數,要求支持操作: 1.修改某個數的值 2.讀入l,r,k,詢問
【bzoj3638】Cf172 k-Maximum Subsequence Sum 模擬費用流+線段樹區間合並
light 最大連續 範圍 區間和 data while define query lmin 題目描述
給一列數,要求支持操作: 1.修改某個數的值 2.讀入l,r,k,詢問在[l,r]內選不相交的不超過k個子段,最大的和是多少。
輸入
The fi
BZOJ.3638.CF172 k-Maximum Subsequence Sum(模擬費用流 線段樹)
() sum 一個 新增 query freopen tdi int 取反 題目鏈接
各種zz錯誤。。簡直要寫瘋
/*
19604kb 36292ms
樸素線段樹:線段樹上每個點維護O(k)個信息,區間合並時O(k^2),總O(mk^2logn)->GG
考慮費用流
【BZOJ3638】k-Maximum Subsequence Sum
【題目連結】
【五倍經驗連結】
【思路要點】
容易發現一種可行的費用流建邊。
用線段樹模擬上述費用流,我們需要實現查詢區間最大子段和和區間取反。
時間複雜度O(MKLogN)O(MKLogN)。
【程式碼】
CF280D k-Maximum Subsequence Sum 線段樹
題目大意:
給你一個長度為n(1<=n<=105)n(1<=n<=105)的序列,支援兩種操作:
1.修改某個位置的值。
2.在區間[l,r][l,r]裡選擇不超過k(1<=k<=20)k(1<=k<=20)
【CF280D】 k-Maximum Subsequence Sum ,線段樹模擬費用流
line 最大 operator 優優 理解 modify pushd 關於 做的 昨天考試被教育了一波。為了學習一下\(T3\)的科技,我就找到了這個遠古時期的\(cf\)題(雖然最後\(T3\)還是不會寫吧\(QAQ\))
顧名思義,這個題目其實可以建成一個費用流的模型
1007 Maximum Subsequence Sum(25 分)【最大連續子序列和】
題意:求最大連續子序列和並記錄該序列的頭尾元素
#include <bits/stdc++.h>
using namespace std;
int N;
int main()
{
cin>>N;
vector<int>
01-複雜度2 Maximum Subsequence Sum(最大子列和問題變化)
一、題目:
01-複雜度2 Maximum Subsequence Sum (25 分)
Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is de
PAT 1007 Maximum Subsequence Sum(最大子串和)
原題地址
求出給定數字串的最大子串和,以及這個最大子串和的首尾元素。(若有多個最大子串則取最靠左的那個)
解題思路
本題基本上是最大子串和的裸題,只是增加了一個輸出首尾元素的要求。
PAT甲級--1007 Maximum Subsequence Sum (25)(25 分)【最大子序列和及其起始和終點】
1007 Maximum Subsequence Sum (25)(25 分)
Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A continuous subsequence is defined to
資料結構學習筆記(1):Maximum Subsequence Sum最大子列和
問題思路分析:就是課堂上所講過的最大子列和問題,不過需要輸出子列頭和尾的項根據網上的資料,摹寫程式碼為具體實現:#include<iostream>
using namespace std;
int main (){
int N ;
cin >>
PAT Maximum Subsequence Sum[最大子序列和,簡單dp]
ace 序號 fin nts 很好 lag malle test 二次 1007 Maximum Subsequence Sum (25)(25 分)
Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }.
1007 Maximum Subsequence Sum - 最大連續子序
思路:
原則是:用now表示當前的判斷,在把多個元素加和的時候,若加到a[i]的時候小於0,那麼捨去a[i],繼續向後判斷,設ans=-1記錄最大值(設為-1的原因是要處理0開頭的情況)
若sum==0那麼我們不要(題上要求i,j最小),但如果第1個數是0那麼就要
用tleft表示臨時的
1007 Maximum Subsequence Sum (25 point(s))
1007 Maximum Subsequence Sum (25 point(s))
部分未通過 22分
#include<iostream>
#include<vector>
#include<algorithm>
using namespa
1007 Maximum Subsequence Sum (25 分)
1007 Maximum Subsequence Sum (25 分)
Given a sequence of K integers { N1, N2, ..., NK }. A continuou
PAT--1007 Maximum Subsequence Sum (25 分)
1007 Maximum Subsequence Sum (25 分)
Given a sequence of K integers { N1, N2 , …, N,K }. A continuous subsequence is defined to be { N
01-複雜度2 Maximum Subsequence Sum(25 分)
Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } wher
1007 Maximum Subsequence Sum(25 分)(PAT甲級)
Problem Description:
Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+
PTA 01-複雜度2 Maximum Subsequence Sum (25 分)
01-複雜度2 Maximum Subsequence Sum (25 分)
Given a sequence of K integers { N1, N2, …, NK }. A continuous subsequence is defin