4541: [Hnoi2016]矿区
Posted AωD!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4541: [Hnoi2016]矿区相关的知识,希望对你有一定的参考价值。
学习了一下平面图剖分的姿势,orz cbh
每次只要随便选择一条边,然后不停尽量向左转就行
#include <bits/stdc++.h> #define N 1300000 #define M 5000013 #define LL long long #define pb push_back using namespace std; LL n, m, k; struct point { LL x, y; } S[N]; vector <LL> bi[N]; vector <LL> re[N], vis[N], s1[N], s2[N]; vector <LL> bt[N], ca[N], cb[N]; LL tot_are; LL siz[N], sum1[N], sum2[N], tot[N]; LL nwc; LL comp(LL a, LL b) { return atan2(S[a].y - S[nwc].y, S[a].x - S[nwc].x) > atan2(S[b].y - S[nwc].y, S[b].x - S[nwc].x); } LL getsiz(point a, point b, point c) { return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); } namespace addr { LL hs[M]; LL dt[M]; LL get(LL a, LL b) { return 1ll * a * 1000000 + b; } LL & find(LL a, LL b) { LL p = get(a, b); LL q = p % M; while (hs[q] && hs[q] != p) q = (q + 1) % M; hs[q] = p; return dt[q]; } } LL tvis[N], fa[N]; void dfs(LL t) { //cout << t << "\\n"; tvis[t] = 1; sum1[t] = siz[t] * siz[t]; sum2[t] = siz[t] * 2; for (LL i = 0; i < bt[t].size(); ++ i) if (!tvis[bt[t][i]]) { dfs(bt[t][i]); fa[bt[t][i]] = t; sum1[t] += sum1[bt[t][i]]; sum2[t] += sum2[bt[t][i]]; s1[ca[t][i]][addr :: find(ca[t][i], cb[t][i])] = sum1[bt[t][i]]; s2[ca[t][i]][addr :: find(ca[t][i], cb[t][i])] = sum2[bt[t][i]]; s1[cb[t][i]][addr :: find(cb[t][i], ca[t][i])] = -sum1[bt[t][i]]; s2[cb[t][i]][addr :: find(cb[t][i], ca[t][i])] = -sum2[bt[t][i]]; } } LL read() { LL x=0,f=1;char ch=getchar(); while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')f=-1;ch=getchar();} while(ch>=\'0\'&&ch<=\'9\'){x=x*10+ch-\'0\';ch=getchar();} return x*f; } LL c = 0; int main() { //freopen("mine2.in", "r", stdin); n = read(); m = read(); k = read(); for (LL i = 1; i <= n; ++ i) S[i].x = read(), S[i].y = read(); for (LL i = 1; i <= m; ++ i) { LL a, b; a = read(); b = read(); bi[a].push_back(b); bi[b].push_back(a); } for (LL i = 1; i <= n; ++ i) re[i].resize(bi[i].size()), s1[i] = s2[i] = vis[i] = re[i]; for (LL i = 1; i <= n; ++ i) nwc = i, sort(bi[i].begin(), bi[i].end(), comp); for (LL i = 1; i <= n; ++ i) for (LL j = 0; j < bi[i].size(); ++ j) addr :: find(i, bi[i][j]) = j; for (LL i = 1; i <= n; ++ i) for (LL j = 0; j < bi[i].size(); ++ j) re[i][j] = addr :: find(bi[i][j], i); for (LL i = 1; i <= n; ++ i) for (LL j = 0; j < bi[i].size(); ++ j) if (!vis[i][j]) { tot_are ++; for (LL k = i, p = j; !vis[k][p]; ) { siz[tot_are] += getsiz(S[i], S[k], S[bi[k][p]]); vis[k][p] = tot_are; LL np = (re[k][p] + 1) % bi[bi[k][p]].size(); k = bi[k][p]; p = np; } if (siz[tot_are] < 0) c = tot_are; } for (LL i = 1; i <= n; ++ i) for (LL j = 0; j < bi[i].size(); ++ j) bt[vis[i][j]].push_back(vis[bi[i][j]][re[i][j]]), ca[vis[i][j]].push_back(i), cb[vis[i][j]].push_back(bi[i][j]); dfs(c); for (LL i = 1, last = 0; i <= k; ++ i) { LL d, ns1 = 0, ns2 = 0; d = read(); d = (d + last) % n + 1; LL fs, ls, nw; fs = read(); fs = (fs + last) % n + 1; ls = fs; for (LL j = 2; j <= d; ++ j, ls = nw) { nw = read(); nw = (nw + last) % n + 1; ns1 += s1[ls][addr :: find(ls, nw)]; ns2 += s2[ls][addr :: find(ls, nw)]; } ns1 += s1[ls][addr :: find(ls, fs)]; ns2 += s2[ls][addr :: find(ls, fs)]; LL g = __gcd(ns1, ns2); cout << ns1 / g << " " << ns2 / g << "\\n"; last = ns1 / g; } }
放在class里的东西还会爆栈QAQ,以后不敢用了
以上是关于4541: [Hnoi2016]矿区的主要内容,如果未能解决你的问题,请参考以下文章