日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[codevs 1743] 反转卡片

發布時間:2025/3/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [codevs 1743] 反转卡片 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://codevs.cn/problem/1743/

題解

  • 思路:采用標記的方式減少操作。rev表示該節點及子樹需要翻轉。如果在kth()查詢第k位置的卡片時走到這個節點o,就pushdown(o),把標記傳到子節點,反轉左右子節點。如果要反轉的區間為[l, r],在rever操作中,將l-1伸展到根,再將r+1節點伸展到右節點。那么對應區間可以轉化為ch[ch[o][1]][0]節點所對應的樹,給它打標記即可。

  • 注意的問題:
    1.需要虛擬節點,因為思路中rever操作很有風險。建立虛擬節點后各個點的編號要變。
    2.在將某節點伸展到根的右節點時,注意k的取值,要減去根左節點的s值+1。見代碼。
    3.要注意pushdown操作的位置,共有三處需要:kth中一次,splay中兩次。
    3.定義了宏,挺好用的。

代碼

總時間耗費: 1782ms
總內存耗費: 5 MB

#include<cstdio> #include<algorithm> using namespace std;const int maxn = 300000 + 10; const int maxc = 100000;int n, root, ch[maxn][2], s[maxn], v[maxn]; bool rev[maxn];#define lc ch[o][0] #define rc ch[o][1]void update(int o) { s[o] = s[lc] + s[rc] + 1; }void rotate(int& o, int d) { int k = ch[o][d^1]; ch[o][d^1] = ch[k][d]; ch[k][d] = o; update(o); update(k); o = k; }void pushdown(int o) { rev[o]^=1; rev[lc]^=1; rev[rc]^=1; swap(lc, rc); }int cmp(int o, int k) { if(s[lc]+1 == k) return -1; return k < s[lc]+1 ? 0 : 1; }void splay(int& o, int k) {if(rev[o]) pushdown(o); //noticeint d = cmp(o, k);if(d == -1) return;if(d == 1) k -= s[lc] + 1;int p = ch[o][d];if(rev[p]) pushdown(p); //noticeint d2 = cmp(p, k);int k2 = (d2 == 0) ? k : k-s[ch[p][0]]-1;if(d2 != -1) {splay(ch[p][d2], k2);if(d == d2) rotate(o, d^1); else rotate(ch[o][d], d);}rotate(o, d^1); }void rever(int& o, int L, int R) { splay(o, L); splay(rc, R-s[lc]+1); //R+2 - (s[lc]+1)rev[ch[rc][0]] ^= 1; }void build(int L, int R, int P, int d) {if(L == R) { s[L] = 1; ch[P][d] = L; return; }int M = (L+R) >> 1;if(M-1 >= L) build(L, M-1, M, 0); if(R >= M+1) build(M+1, R, M, 1);ch[P][d] = M; update(M); }int kth(int o, int k) {if(rev[o]) pushdown(o);if(s[lc]+1 == k) return o;if(s[lc] >= k) return kth(lc, k); return kth(rc, k-s[lc]-1); }int main() {scanf("%d", &n);for(int i = 2; i <= n+1; i++) scanf("%d", &v[i]);build(1, n+2, 0, 0); root = (n+3) >> 1;int first, c = 0;while((first = v[kth(root, 2)]) != 1) {rever(root, 1, first);if(++c > maxc) { c = -1; break; }}printf("%d\n", c);return 0; }

總結

以上是生活随笔為你收集整理的[codevs 1743] 反转卡片的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。