20200724T2 【NOIP2015模擬10.28B組】聖章-精靈使的魔法語
Description
【背景介紹】
“魔法???算了吧,這種東西我肯定學不了的啦!”明明是個劍士,卻被眼前這位洋洋自得的精靈使——弗洛莉拖出去學魔法,真是個沒事找茬的傢伙……
“沒事啦。作為一名冒險者會發生很多情況,中毒啦,受傷啦,被咒語束縛之類的,沒有魔法就很難辦的呀!”她到是好像一副什麼都懂的樣子,真是令人火大。
“都說我是個人類了,魔法這種東西學起來很困難的吧!”我只好找個看似靠譜的藉口。
然而,她那不屈不撓的聲音又響了起來:“人類雖然與自然的共鳴,也就是魔法的連線較少,但如果認真訓練的話還是可以做到的呢!總之,試試看吧!念念咒語之類的!”弗洛莉把魔法書一把拍在了我面前。
“真是的,弗洛莉才是老拖我的後腿呢!”我沒好氣地笑道……
“裡修!你……”她從牙縫裡擠出了一個字。我頓感不妙,見到了那張比魔鬼還可怕的扭曲的面孔。“真是個魔法的天才哪!”她一掃之前不愉快的表情,想我露出大拇指,好像是在誇獎我的樣子。
【題目描述】
“倫福薩”【即"("】和“密西卡”【即")"】是兩種不同的精靈咒語,已知一個成功的咒語符合如下的規定:
每一個密西卡之前都可以對應匹配到一個倫福薩,即為一個合法的精靈魔法咒語。
方便的是,我們將“倫福薩”視為"(",“密西卡”視為")",合法的精靈魔法咒語即為一個合法的括號序列。
如:"((()))""(()())""()()()"均為合法的魔法咒語,")(""())(""(("均為不合法的魔法咒語。
Input
第一行兩個正整數n,m,表示我現在含有的咒語元素(“倫福薩”【即"("】和“密西卡”【即")"】)的個數以及弗洛莉給我的任務個數,
第二行包含n個字元(“倫福薩”【即"("】或“密西卡”【即")"】)表示一開始弗洛莉給我的咒語片段。
以下m行包括兩種任務:
Changex,表示弗洛莉將位置為x上的咒語片段進行一次變換(原來是“倫福薩”【即"("】變為“密西卡”【即")"】,原來是“密西卡”【即")"】變為“倫福薩”【即"("】)。
Querylr,詢問從l到r的區間的片段,在這個片段前最少添上多少個倫福薩”【即"("】,在這個片段後最少添上多少個“密西卡”【即")"】可以成為合法的魔法序列。
Output
每個詢問對應一行答案,每行包括兩個整數,表示在這個片段前最少添上多少個倫福薩”【即"("】,在這個片段後最少添上多少個“密西卡”【即")"】可以成為合法的魔法序列。
Sample Input
64
(()()(
Query13
Query36
Change6
Query16
Sample Output
01
11
00
【樣例解釋】
1.片段為“(()”最右邊填1個)即可。
2.片段為“)()(”最左邊添1個(最右邊添1個)即可。
3.片段為“(()())”已經是合法片段。不需新增。
Data Constraint
對於20%的資料,1≤n,m≤100
對於40%的資料,1≤n,m≤3000
另外含有30%的資料,資料中不包含修改操作。
對於100%的資料,1≤n,m≤150,000
solution
顯然線段樹
不過update不太好處理
所以copy zjy的
時間複雜度為O(m log n)
code
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 #include<vector> 8 #include<stack> 9 #include<set> 10 #include<deque> 11 #include<map> 12 using namespace std; 13 14 template <typename T> void read(T &x) { 15 x = 0; int f = 1; char c; 16 for (c = getchar(); c < '0' || c > '9'; c = getchar()) if (c == '-') f = -f; 17 for (; c >= '0' && c <= '9'; c = getchar()) x = 10 * x + c - '0' ; 18 x *= f; 19 } 20 template <typename T> void write(T x){ 21 if (x < 0) putchar('-'), x = -x; 22 if (x > 9) write(x / 10); 23 putchar(x % 10 + '0'); 24 } 25 template <typename T> void writeln(T x) { write(x); putchar('\n'); } 26 template <typename T> void writesn(T x) { write(x); putchar(' '); } 27 28 #define ll long long 29 #define inf 1234567890 30 #define next net 31 #define P 2147483647 32 #define N 150010 33 #define mid ((l+r)>>1) 34 #define lson (o<<1) 35 #define rson (o<<1|1) 36 #define Re register 37 #define debug puts("zxt") 38 39 int n , m , x, y; 40 char s[N ],qwq[10]; 41 int a[N ]; 42 struct node{ 43 int left,right; 44 }tree[N << 2], ans; 45 node update(node a, node b) 46 { 47 node kkk; 48 kkk.left = (a.left > b.right ? a.left - b.right : 0) + b.left; 49 kkk.right = (a.left < b.right ? b.right - a.left : 0)+ a.right; 50 return kkk; 51 } 52 void build(int o, int l, int r) 53 { 54 if(l == r) 55 { 56 if(a[l]) tree[o].left++; 57 else tree[o].right++; 58 return; 59 } 60 build(lson, l, mid); 61 build(rson, mid + 1, r); 62 tree[o] = update(tree[lson], tree[rson]); 63 return; 64 } 65 void change(int o, int l, int r, int x) 66 { 67 if(l == r) 68 { 69 a[l] ^= 1; 70 if(a[l] == 1) tree[o].left++, tree[o].right--; 71 else tree[o].left--, tree[o].right++; 72 return; 73 } 74 if(x <= mid) change(lson, l, mid, x); 75 else change(rson, mid + 1, r, x); 76 tree[o] = update(tree[lson], tree[rson]); 77 return; 78 } 79 node query(int o, int l, int r, int L, int R ) 80 { 81 if(l == L && R == r) 82 { 83 return tree[o]; 84 } 85 if(R <= mid) return query(lson, l, mid, L, R); 86 if(L > mid) return query(rson, mid + 1, r, L, R); 87 return update(query(lson, l, mid, L, mid), query(rson, mid + 1, r, mid + 1, R)); 88 } 89 signed main() 90 { 91 //freopen("elf.in","r",stdin); 92 //freopen("elf.out","w",stdout); 93 read(n); read(m ); 94 scanf("%s", s + 1); 95 for(Re int i = 1; i <= n; i++) a[i] = (s[i] == '(' ? 1 : 0); 96 build(1, 1, n); 97 while(m --) 98 { 99 scanf("%s", qwq); 100 if(qwq[0] == 'Q') 101 { 102 read(x); read(y); 103 ans = query(1, 1, n, x, y); 104 writesn(ans.right); writeln(ans.left); 105 } 106 else 107 { 108 read(x); 109 change(1, 1, n, x); 110 } 111 } 112 return 0; 113 }