对应HDU题目:点击打开链接
Time Limit: 2000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64u |
Description
Input
Output
Sample Input
1 10 10 7 7 3 3 5 9 9 8 1 8 Q 6 6 U 3 4 Q 0 1 Q 0 5 Q 4 7 Q 3 5 Q 0 2 Q 4 6 U 6 10 Q 0 9
Sample Output
1 1 4 2 3 1 2 5
Source
题意:给出n个数,m个询问,每个询问包含 (c,a,b) ,c=U时,把下标为a的值改为b,c=Q时,求[a,b]之间的最长连续递增子序列,并输出
思路:线段树区间合并;
对于一段区间[l,r],mid为中间值,要求[a,b]之间(其中a,b在[l,r]内)的lcis,则最长连续递增子序列要么在mid左边,要么在mid右边,要么是mid左右两边都有。所以线段树区间维护的就是3个数组,一个是该区间的lcis,用lcis[rt]表示,一个是从区间左边界数起连续递增序列的个数llcis[rt],一个是从区间右边界数起连续递减序列的个数rlcis[rt]。
试了下两种╮(╯_╰)╭
[0,9] 和 [0,9]
[0,4] [4,9] [0,4] [5,9]
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> #define ms(x,y) memset(x,y,sizeof(x)) #define eps 1e-6 const int MAXN=400000+10; const int INF=1<<30; using namespace std; int value[MAXN/4]; int lcis[MAXN]; int llcis[MAXN]; int rlcis[MAXN]; void up(int rt, int mid, int len) { llcis[rt] = llcis[rt<<1]; rlcis[rt] = rlcis[rt<<1|1]; lcis[rt] = max(lcis[rt<<1], lcis[rt<<1|1]); if( value[mid+1] > value[mid] ){ if(llcis[rt] == len-(len>>1)) llcis[rt] += llcis[rt<<1|1]; if(rlcis[rt] == (len>>1)) rlcis[rt] += rlcis[rt<<1]; lcis[rt] = max(rlcis[rt<<1] + llcis[rt<<1|1], lcis[rt]); } } void update_change(int rt, int left, int right, int pos) { if(left == right) return; if(right - left == 1){ if(value[left] < value[right]){ lcis[rt] = 2; llcis[rt] = 2; rlcis[rt] = 2; } else{ lcis[rt] = 1; llcis[rt] = 1; rlcis[rt] = 1; } return; } int mid=(left+right)>>1; if(mid >= pos) update_change(rt<<1, left, mid, pos); else update_change(rt<<1|1, mid+1, right, pos); up(rt, mid, right-left+1); } int query(int rt, int left, int right, int l, int r) { if(l == left && right == r) return lcis[rt]; int mid=(left + right)>>1; if(mid >= r) return query(rt<<1, left, mid, l, r); else if(mid < l) return query(rt<<1|1, mid+1, right, l, r); else{ int len1=query(rt<<1, left, mid, l, mid); int len2=query(rt<<1|1, mid+1, right, mid+1, r); int len3=0; if(value[mid+1] > value[mid]) len3=min(rlcis[rt<<1], mid-l+1) + min(llcis[rt<<1|1], r-mid); return max(len1, max(len2,len3)); } } void Initialize() { for(int i=0; i<MAXN; i++){ lcis[i]=1; llcis[i]=1; rlcis[i]=1; } } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d", &T); while(T--) { Initialize(); char op; int n,m; int a,b; scanf("%d%d", &n,&m); for(int i=0; i<n; i++){ scanf("%d", &value[i]); update_change(1,0,n-1,i); } while(m--) { scanf(" %c%d%d", &op,&a,&b); if(op == 'U'){ value[a]=b; update_change(1,0,n-1,a); } else{ if(b - a == 1 || b - a == 0){//求相邻的两个数或求一个数 if(value[a] >= value[b]) printf("1\n"); else printf("2\n"); } else printf("%d\n", query(1,0,n-1,a,b));//求三个数以上 } } } return 0; }
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> #define ms(x,y) memset(x,y,sizeof(x)) #define eps 1e-6 const int MAXN=400000+10; const int INF=1<<30; using namespace std; int value[MAXN]; int lcis[MAXN]; int llcis[MAXN]; int rlcis[MAXN]; void up(int rt, int len) { int llen,rlen; llen=rlen=(len>>1) + 1; if((len&1) == 0) llen--; llcis[rt] = llcis[rt<<1]; rlcis[rt] = rlcis[rt<<1|1]; if(llcis[rt] == llen) llcis[rt] += llcis[rt<<1|1] - 1; if(rlcis[rt] == rlen) rlcis[rt] += rlcis[rt<<1] - 1; lcis[rt] = max(rlcis[rt<<1] + llcis[rt<<1|1] - 1, max(lcis[rt<<1], lcis[rt<<1|1])); } void update_change(int rt, int left, int right, int pos) { if(right - left ==1){ int lval=value[left]; int rval=value[right]; if(lval < rval){ lcis[rt] = 2; llcis[rt] = 2; rlcis[rt] = 2; } else{ lcis[rt] = 1; llcis[rt] = 1; rlcis[rt] = 1; } return; } int mid=(left+right)>>1; if(mid > pos) update_change(rt<<1, left, mid, pos); else if(mid < pos) update_change(rt<<1|1, mid, right, pos); else{ update_change(rt<<1, left, mid, pos); update_change(rt<<1|1, mid, right, pos); } up(rt, right-left+1); } int query(int rt, int left, int right, int l, int r) { if(l == left && right == r) return lcis[rt]; int mid=(left + right)>>1; if(mid >= r) return query(rt<<1, left, mid, l, r); else if(mid <= l) return query(rt<<1|1, mid, right, l, r); else{ int len1=query(rt<<1, left, mid, l, mid); int len2=query(rt<<1|1, mid, right, mid, r); int len3=min(rlcis[rt<<1], mid-l+1) + min(llcis[rt<<1|1], r-mid+1) - 1; return max(len1, max(len2,len3)); } } void Initialize() { for(int i=0; i<MAXN; i++){ lcis[i]=1; llcis[i]=1; rlcis[i]=1; value[i]=0; } } int main() { //freopen("in.txt","r",stdin); //freopen("c:\\Users\\Administrator\\Desktop\\out.txt","w",stdout); int T; scanf("%d", &T); while(T--) { Initialize(); char op; int n,m; int a,b; scanf("%d%d", &n,&m); for(int i=0; i<n; i++){ scanf("%d", &value[i]); update_change(1,0,n-1,i); } #if 0 for(int j=1; j<=31; j++){ cout<<j<<": "<<lcis[j]<<endl; cout<<" "<<llcis[j]<<endl; cout<<" "<<rlcis[j]<<endl; } cout<<endl; #endif while(m--) { scanf(" %c%d%d", &op,&a,&b); //cin>>op>>a>>b; if(op == 'U'){ value[a]=b; update_change(1,0,n-1,a); } else{ if(b - a == 1 || b - a == 0){ if(value[a] >= value[b]) printf("1\n"); else printf("2\n"); } else printf("%d\n", query(1,0,n-1,a,b)); } } } return 0; }