标签:cst == blog php div center include 三元 mst
4
1011
1 1 2 3
1
1 2
先把相邻男女加入堆中,形式为三元组$(i,j,val)$,表示编号为$i$和$j$的人,相差为$val$
这是一个以$val$为关键值的小根堆
每次不停地弹,直到弹到两人都没跳过
然后删除这两个人,这两个人删了之后会有两边的人相邻,判断是否为男女,是则加入堆
至于左右的人用双向链表维护即可,又想骗我写并查集
#include <queue> #include <cstdio> using namespace std; char buf[10000000], *ptr = buf - 1; inline int readint(){ int f = 1, n = 0; char ch = *++ptr; while(ch < ‘0‘ || ch > ‘9‘){ if(ch == ‘-‘) f = -1; ch = *++ptr; } while(ch <= ‘9‘ && ch >= ‘0‘){ n = (n << 1) + (n << 3) + ch - ‘0‘; ch = *++ptr; } return f * n; } const int maxn = 200000 + 10; int N, l[maxn], r[maxn], type[maxn], val[maxn]; bool out[maxn] = {false}; struct Node{ int a, b, v; Node(){} Node(int _a, int _b, int _v): a(_a), b(_b), v(_v){} }t; class cmp{ public: bool operator () (const Node &x, const Node &y){ return x.v == y.v ? x.a > y.a : x.v > y.v; } }; inline int abs_(int a){ return a >= 0 ? a : -a; } priority_queue<Node, vector<Node>, cmp> q; int cnt = 0, ansa[maxn], ansb[maxn]; int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); N = readint(); char tmp; for(int i = 1; i <= N; i++){ tmp = *++ptr; while(tmp < ‘0‘ || tmp > ‘9‘) tmp = *++ptr; type[i] = tmp - ‘0‘; l[i] = i - 1; r[i] = i + 1; } for(int i = 1; i <= N; i++) val[i] = readint(); for(int i = 1; i < N; i++) if(type[i] != type[i + 1]) q.push(Node(i, i + 1, abs_(val[i] - val[i + 1]))); while(!q.empty()){ t = q.top(); q.pop(); if(out[t.a] || out[t.b]) continue; out[t.a] = out[t.b] = true; cnt++; ansa[cnt] = t.a; ansb[cnt] = t.b; int lx = l[t.a], rx = r[t.b]; r[lx] = rx; l[rx] = lx; if(lx != 0 && rx != N + 1 && type[lx] != type[rx]) q.push(Node(lx, rx, abs_(val[lx] - val[rx]))); } printf("%d\n", cnt); for(int i = 1; i <= cnt; i++) printf("%d %d\n", ansa[i], ansb[i]); return 0; }
标签:cst == blog php div center include 三元 mst
原文地址:http://www.cnblogs.com/ruoruoruo/p/7563490.html