HDU 3308 线段树求区间最长连续上升子序列长度
生活随笔
收集整理的這篇文章主要介紹了
HDU 3308 线段树求区间最长连续上升子序列长度
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:兩種操作,Q L R查詢L - R 的最長連續上升子序列長度,U pos val 單點修改值
#include <bits/stdc++.h> #define N 100005 using namespace std; int lcs[N<<2],pre[N<<2],suf[N<<2],arr[N];維護區間lcs長度,以左端點為起點的lcs長度,以右端點為終點的lcs長度,這么做是為了處理區間合并后區間總lcs值的更新 void pushup(int l,int r,int rt) {int m=(l+r)>>1;lcs[rt]=max(lcs[rt<<1],lcs[rt<<1|1]);if(arr[m]<arr[m+1])lcs[rt]=max(lcs[rt],suf[rt<<1]+pre[rt<<1|1]);pre[rt]=pre[rt<<1];if(pre[rt<<1]==m-l+1&&arr[m]<arr[m+1])pre[rt]+=pre[rt<<1|1];suf[rt]=suf[rt<<1|1];if(suf[rt<<1|1]==r-m&&arr[m]<arr[m+1])suf[rt]+=suf[rt<<1]; } void build(int l,int r,int rt) {if(l==r){suf[rt]=pre[rt]=lcs[rt]=1;return;}int m=(l+r)>>1;build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(l,r,rt); } void update(int pos,int val,int l,int r,int rt) {if(l==r){arr[l]=val;return;}int m=(l+r)>>1;if(pos<=m)update(pos,val,l,m,rt<<1);if(pos>m)update(pos,val,m+1,r,rt<<1|1);pushup(l,r,rt); } int query(int L,int R,int l,int r,int rt) {if(L<=l&&r<=R)return lcs[rt];int m=(l+r)>>1;int mx=0;if(L<=m)mx=max(mx,query(L,R,l,m,rt<<1));if(m<R)mx=max(mx,query(L,R,m+1,r,rt<<1|1));//這時的mx只是各子區間的最大值,必須考慮子區間連接之后的狀態int prex=min(R-m,pre[rt<<1|1]);int sufx=min(m-L+1,suf[rt<<1]);if(arr[m]<arr[m+1])mx=max(mx,prex+sufx);return mx; } int main() {int t,n,m;cin>>t;while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",arr+i);build(1,n,1);char cmd[10];int l,r;while (m--){scanf("%s%d%d",cmd,&l,&r);if(cmd[0]=='U')update(l+1,r,1,n,1);else printf("%d\n",query(l+1,r+1,1,n,1));}}return 0; }?
轉載于:https://www.cnblogs.com/xusirui/p/9434488.html
總結
以上是生活随笔為你收集整理的HDU 3308 线段树求区间最长连续上升子序列长度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python网络编程(OSI模型、网络协
- 下一篇: 应用负载均衡之LVS(三):ipvsad