• [HNOI2016]矿区


    题面

    给定平面上许多的区域,每次询问一些点所包围的子区域的面积平方之和与总面积之和之比,强制在线。

    ( ext{Solution})

    毒瘤至极

    显然我们要维护每一个小区域的面积,由于我们要维护的是一个面,所以我们将平面图转对偶图(不会的戳这里)。面的信息就缩在一个点中,以无穷域为根随便弄出个生成树,对于任意点x处理出以x为根的子树所代表的区域的面积。

    那么对于一组询问,我们扫描它的每一条边,看它的反向边是否是它的父亲,如果是,则加上自己子树的面积,否则减去子树的面积。

    显然这么毒瘤的题我是码不出的。
    不过如果之前学过对偶图,思维难度并不大。

    #include <set>
    #include <vector>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define LL long long
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define GO debug("GO
    ")
    
    inline int rint() {
      register int x = 0, f = 1; register char c;
      while (!isdigit(c = getchar())) if (c == '-') f = -1;
      while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
      return x * f;
    }
    
    template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
    template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
    
    const int N = 2e5 + 10, M = 1.2e6 + 5;
    const double eps = 1e-10;
    
    #define Iter vector<Edge>::iterator
    
    LL ans1, ans2;
    int n, m, Q, tot = 1, cnt, root;
    
    struct vec {
      int x, y;
      vec(int _x = 0, int _y = 0) {x = _x, y = _y;}
      vec operator- (const vec &b) const 
      { return vec(x - b.x, y - b.y); }
      LL operator* (const vec &b) const
      { return 1ll * x * b.y - 1ll * y * b.x;}
    } P[N];
    
    struct Edge {
      int id, u, v; double angle;//atan2 rad
      bool operator< (const Edge &b) const
      { return fabs(angle - b.angle) < eps ? v < b.v : angle < b.angle; }
    } E[M];
    
    int nxt[M], pos[M], fa[M], vis[M], intree[M], ask[M];
    LL s[M], ss[M];
    
    vector<Edge> G[N], tree[M];
    
    void add(int u, int v) {
      E[++tot] = (Edge) {tot, u, v, atan2(P[v].y - P[u].y, P[v].x - P[u].x)};
      G[u].push_back(E[tot]);
    }
    
    void Build() {
      for (int i = 1; i <= n; ++ i)
        sort(G[i].begin(), G[i].end());
      for (int i = 2; i <= tot; ++ i) {
        int v = E[i].v;
        Iter it = lower_bound(G[v].begin(), G[v].end(), E[i ^ 1]);
        if (it == G[v].begin()) it = G[v].end();
        --it;
        nxt[i] = it->id;
      }
      for (int i = 2; i <= tot; ++ i) {
        if (pos[i]) continue;
        pos[i] = pos[nxt[i]] = ++cnt;
        for (int j = nxt[i]; E[j].v != E[i].u; j = nxt[j], pos[j] = cnt) 
          s[cnt] += (P[E[j].u] - P[E[i].u]) * (P[E[j].v] - P[E[i].u]);
        if (s[cnt] <= 0) root = cnt;
      }
      for (int i = 2; i <= tot; ++ i) 
        tree[pos[i]].push_back((Edge){i, pos[i], pos[i ^ 1]});
    }
    
    void DFS(int u, int las) {
      fa[u] = las;
      ss[u] = s[u] * s[u];
      s[u] <<= 1;
      vis[u] = 1;
      for (int i = 0; i < tree[u].size(); ++ i) {
        int v = tree[u][i].v;
        if (vis[v]) continue;
        intree[tree[u][i].id] = intree[tree[u][i].id ^ 1] = 1;
        DFS(v, u);
        s[u] += s[v];
        ss[u] += ss[v];
      }
    }
    
    void solve() {
      while (Q --) {
        int tmp = rint(); tmp = (tmp + ans1) % n + 1;
        for (int i = 1; i <= tmp; ++ i) 
          ask[i] = (rint() + ans1) % n + 1;
        ask[tmp + 1] = ask[1];
        ans1 = ans2 = 0;
        for (int i = 1; i <= tmp; ++ i) {
          int x = ask[i], y = ask[i + 1];
          Edge xhc = (Edge) {0, x, y, atan2(P[y].y - P[x].y, P[y].x - P[x].x)};
          Iter it = lower_bound(G[x].begin(), G[x].end(), xhc);
          int id = it->id;
          if (!intree[id]) continue;
          if (fa[pos[id]] == pos[id ^ 1]) 
            ans1 += ss[pos[id]], ans2 += s[pos[id]];
          else 
            ans1 -= ss[pos[id ^ 1]], ans2 -= s[pos[id ^ 1]];
        }
          LL gcd = __gcd(ans1, ans2);
          ans1/=gcd, ans2/=gcd;
          printf("%lld %lld
    ", ans1, ans2);
      }
    }
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("xhc.in", "r", stdin);
      freopen("xhc.out", "w", stdout);
    #endif
      n = rint(), m = rint(), Q = rint();
      for (int i = 1; i <= n; ++ i) {
        int u = rint(), v = rint();
        P[i] = vec(u, v);
      }
      for (int i = 1; i <= m; ++ i) {
        int x = rint(), y = rint();
        add(x, y), add(y, x);
      }
      Build();
      DFS(root, 0);
      solve();
    }
    
  • 相关阅读:
    智慧城市开发模式研究
    区域经济、地理信息、互联网三者交叉之行业背景分析
    《矿产经济与管理》读书笔记
    郝寿义、安虎森《区域经济学》读书笔记
    京津冀区域货流预测与分析
    关于产业链招商的背景、内涵、特征和意义
    《政府与企业招商引资战略操作实务》读书笔记
    网站seo优化
    弹出窗口里有“确定”和“取消”两个按钮
    解决在网页里设置锚点后,链接不到相应位置
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10599242.html
Copyright © 2020-2023  润新知