题目描述:
Petya loves lucky numbers very much. Everybody knows that lucky numbers are positive integers whose decimal record contains only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.
Petya brought home string s with the length of n. The string only consists of lucky digits. The digits are numbered from the left to the right starting with 1. Now Petya should execute m queries of the following form:
- switch l r — "switch" digits (i.e. replace them with their opposites) at all positions with indexes from l to r, inclusive: each digit 4 is replaced with 7 and each digit 7 is replaced with 4 (1 ≤ l ≤ r ≤ n);
- count — find and print on the screen the length of the longest non-decreasing subsequence of string s.
Subsequence of a string s is a string that can be obtained from s by removing zero or more of its elements. A string is called non-decreasing if each successive digit is not less than the previous one.
Help Petya process the requests.
The first line contains two integers n and m (1 ≤ n ≤ 106, 1 ≤ m ≤ 3·105) — the length of the string s and the number of queries correspondingly. The second line contains n lucky digits without spaces — Petya's initial string. Next m lines contain queries in the form described in the statement.
For each query count print an answer on a single line.
题意:给定由4和7组成的序列,有两个操作:(1) switch l f : 将区间[l,f]中的4变成7,7变成4 (2) count : 输出整个序列的最长上升子序列
解题思路: 这是一道中规中矩的线段树的题,对于每个线段树的结点需要维护四个值:序列中4的数目num4,序列中7的数目num7,最长上升序列大小rise,最长下降序列大小down。 合并操作:对于每个区间合并,num4和num7就不用我说了,rise取 左区间的num4+右区间的rise 与 左区间的rise+右区间的num7中的最大值,同理 down取 左区间num7+右区间down 与 左区间down+右区间的num4的最大值。直接看代码吧。
AC代码:
#include<bits/stdc++.h> #define Mid ((l+r)>>1) #define lson (rt<<1)+1,l,Mid #define rson (rt<<1)+2,Mid+1,r #define ll (rt<<1)+1 #define rr (rt<<1)+2 using namespace std; const int MAX = 1000010; char str[MAX]; struct Tree{ int num4; int num7; int down; int rise; }seg[(MAX<<2)+1]; int swi[(MAX<<2)+1]; void pushup(int rt) { seg[rt].num4 = seg[ll].num4 + seg[rr].num4; seg[rt].num7 = seg[ll].num7 + seg[rr].num7; seg[rt].down = max(seg[ll].num7 + seg[rr].down, seg[ll].down + seg[rr].num4); seg[rt].rise = max(seg[ll].num4 + seg[rr].rise, seg[ll].rise + seg[rr].num7); } void build(int rt, int l, int r) { swi[rt] = 0; if(l == r) { if(str[l] == '4') { seg[rt].num4=seg[rt].rise=seg[rt].down = 1; seg[rt].num7=0; return ; } else { seg[rt].num7=seg[rt].rise=seg[rt].down=1; seg[rt].num4 = 0; return ; } } else { build(lson); build(rson); pushup(rt); } } void pushDown(int rt) { if(swi[rt] != 0) { swi[ll] += swi[rt]; swi[rr] += swi[rt]; if(swi[rt]&1) { swap(seg[ll].num4,seg[ll].num7); swap(seg[ll].rise,seg[ll].down); swap(seg[rr].num4,seg[rr].num7); swap(seg[rr].rise,seg[rr].down); } swi[rt] = 0; } } void update(int rt, int l, int r, int L, int R) { if(L <= l && R >= r) { swi[rt] += 1; swap(seg[rt].num4,seg[rt].num7); swap(seg[rt].rise,seg[rt].down); } else { pushDown(rt); if(L <= Mid) update(lson,L,R); if(R > Mid) update(rson,L,R); pushup(rt); } } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { scanf("%s",str); //memset(swi,0,sizeof(swi)); build(0,0,n-1); char input[10]; int l,r; for(int i=0; i<m; i++) { scanf("%s",input); if(input[0] == 's') { scanf("%d %d",&l,&r); update(0,0,n-1,l-1,r-1); } else { printf("%d ",seg[0].rise); } } } return 0; }