【Foreign】數據結構C [線段樹]
阿新 • • 發佈:2017-10-14
text 信息 lap sid list padding 單點 block word
維護一棵線段樹,用並查集判斷兩點是否在一個塊內。
數據結構C
Time Limit: 20 Sec Memory Limit: 512 MBDescription
Input
Output
Sample Input
Sample Output
HINT
Solution
首先,D操作為刪除操作顯然不可做,又發現這道題可以離線處理,那麽我們考慮倒著來,維護加入操作。
那麽這時候,D操作就變為了合並操作,那麽這時候我們只需要維護一個:可以支持單點修改、查詢第 k 大、信息可合並的數據結構即可。
顯然構建若幹棵權值線段樹即可!對於每個聯通塊
這時候,D操作顯然判斷一下兩點是否在一個聯通塊內,不在則合並兩棵線段樹;Q操作就是查詢第 k 大,在樹上二分即可;C操作就是原來值個數-1,新加入值個數+1。
就簡單地解決了這題啦!(本質上就是BZOJ1926弱化 + BZOJ1015 QWQ)
Code
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6View Code#include<cmath> 7 using namespace std; 8 9 const int ONE = 1000005; 10 const int INF = 2e6; 11 const int Base = 1e6; 12 13 int n, m; 14 int opt, x, val; 15 int Val[100005]; 16 char s[5]; 17 18 int Ans[300005], ans_num = 0; 19 20 int fat[100005]; 21 22 int Num = 0, del[100005]; 23 struct power {int opt, x, val;} oper[ONE]; 24 struct point {int x, y;} a[100005]; 25 int total = 0; 26 struct seg 27 { 28 int root; 29 int left, right; 30 int val; 31 }Node[ONE * 4]; 32 33 int get() 34 { 35 int res=1,Q=1; char c; 36 while( (c=getchar())<48 || c>57) 37 if(c==‘-‘)Q=-1; 38 if(Q) res=c-48; 39 while((c=getchar())>=48 && c<=57) 40 res=res*10+c-48; 41 return res*Q; 42 } 43 44 int Find(int x) 45 { 46 if(fat[x] == x) return x; 47 return fat[x] = Find(fat[x]); 48 } 49 50 void Un(int x, int y) 51 { 52 int f1 = Find(x), f2 = Find(y); 53 if(f1 != f2) fat[f1] = f2; 54 } 55 56 void Update(int &i, int l, int r, int Val, int opt) //pos = Val , + opt 57 { 58 if(!i) i = ++total; 59 60 Node[i].val = Node[i].val + opt; 61 62 if(l == r) return; 63 int mid = l + r >> 1; 64 65 if(Val <= mid) Update(Node[i].left, l, mid, Val, opt); 66 else Update(Node[i].right, mid + 1, r, Val, opt); 67 68 } 69 70 int Merge(int y, int x) //y merge to x 71 { 72 if(x == 0 || y == 0) return x + y; 73 74 Node[x].val += Node[y].val; 75 Node[x].left = Merge(Node[x].left, Node[y].left); 76 Node[x].right = Merge(Node[x].right, Node[y].right); 77 78 return x; 79 } 80 81 int Query(int i, int l, int r, int k) //k da 82 { 83 if(l == r) return l; 84 int mid = l + r >> 1, Val = Node[ Node[i].right ].val; 85 86 if(k > Val) 87 return Query(Node[i].left, l, mid, k - Val); 88 else 89 return Query(Node[i].right, mid + 1, r, k); 90 } 91 92 void Deal_first() 93 { 94 for(int i = 1; i <= n; i++) 95 fat[i] = i, Node[i].root = ++total; 96 for(int i = 1; i <= m; i++) 97 if(del[i] != 1) Un(a[i].x, a[i].y); 98 for(int i = 1; i <= n; i++) 99 Update(Node[Find(i)].root, 0, INF, Val[i], 1); 100 } 101 102 void Deal_add(int x, int y) 103 { 104 x = Find(x), y = Find(y); 105 if(x == y) return; 106 Merge(Node[x].root, Node[y].root); 107 fat[x] = y; 108 } 109 110 void Deal_query(int root, int k) 111 { 112 root = Find(root); 113 if(Node[root].val < k) {Ans[++ans_num] = 0 + Base; return;} 114 Ans[++ans_num] = Query(Node[root].root, 0, INF, k); 115 } 116 117 void Deal_change(int x, int y) //x is point, y is need val 118 { 119 int root = Find(x); 120 Update(Node[root].root, 0, INF, Val[x], -1); 121 Update(Node[root].root, 0, INF, y, 1); 122 Val[x] = y; 123 } 124 125 int main() 126 { 127 n = get(); m = get(); 128 129 for(int i = 1; i <= n; i++) Val[i] = get() + Base; 130 for(int i = 1; i <= m; i++) 131 a[i].x = get(), a[i].y = get(); 132 for(;;) 133 { 134 scanf("%s", s); 135 if(s[0] == ‘E‘) break; 136 if(s[0] == ‘D‘) 137 x = get(), del[x] = 1, oper[++Num] = (power){1, x, 0}; 138 if(s[0] == ‘Q‘) 139 x = get(), val = get(), oper[++Num] = (power){2, x, val}; 140 if(s[0] == ‘C‘) 141 x = get(), val = get(), oper[++Num] = (power){3, x, Val[x]}, Val[x] = val + Base; 142 } 143 144 Deal_first(); 145 for(int i = Num; i >= 1; i--) 146 { 147 if(oper[i].opt == 1) Deal_add(a[ oper[i].x ].x, a[ oper[i].x ].y); 148 if(oper[i].opt == 2) Deal_query(oper[i].x, oper[i].val); 149 if(oper[i].opt == 3) Deal_change(oper[i].x, oper[i].val); 150 } 151 152 for(int i = ans_num; i >= 1; i--) 153 printf("%d\n", Ans[i] - Base); 154 }
- [提交][狀態][討論]
【Foreign】數據結構C [線段樹]