zoukankan      html  css  js  c++  java
  • 洛谷P3242 接水果

    关于矩形与点其实有两种关系。

    一种是每个矩形包含多少点。一种是每个点被多少矩形包含。


    解:因为可以离线所以直接套整体二分。关键是考虑如何能够被覆盖。

    我一开始都是想的树上操作...其实是转化成DFS序。分链和有lca两种情况。

    考虑每个盘子能接住的水果,两端DFS序满足的性质。发现是二维平面上的矩形。

    一个水果就是询问一个点被多少矩形覆盖(能被多少盘子接)。于是整体二分里面扫描线,片改点查用树状数组。

      1 #include <bits/stdc++.h>
      2 
      3 const int N = 80010;
      4 
      5 struct Edge {
      6     int nex, v;
      7 }edge[N << 1]; int tp;
      8 
      9 int e[N], pos[N], ed[N], num, n, fa[N][20], pw[N], d[N]; /// tree
     10 int X[N], xx, ans[N];
     11 
     12 struct Node {
     13     int id, x, y, k, z;
     14     Node(int ID = 0, int X = 0, int Y = 0, int K = 0, int Z = 0) {
     15         id = ID;
     16         x = X;
     17         y = Y;
     18         k = K;
     19         z = Z;
     20     }
     21     inline bool operator <(const Node &w) const {
     22         if(id != w.id) return id < w.id;
     23         return z < w.z;
     24     }
     25 }node[N], t1[N], t2[N], stk[N << 2];
     26 
     27 namespace ta {
     28     int ta[N];
     29     inline void add(int x, int v) {
     30         for(int i = x; i <= n + 1; i += (i & (-i))) {
     31             ta[i] += v;
     32         }
     33         return;
     34     }
     35     inline int ask(int x) {
     36         int ans = 0;
     37         for(int i = x; i >= 1; i -= (i & (-i))) {
     38             ans += ta[i];
     39         }
     40         return ans;
     41     }
     42     inline void del(int x) {
     43         for(int i = x; i <= n + 1; i += (i & (-i))) {
     44             ta[i] = 0;
     45         }
     46         return;
     47     }
     48 }
     49 
     50 inline void add(int x, int y) {
     51     tp++;
     52     edge[tp].v = y;
     53     edge[tp].nex = e[x];
     54     e[x] = tp;
     55     return;
     56 }
     57 
     58 void DFS(int x, int f) {
     59     pos[x] = ++num;
     60     fa[x][0] = f;
     61     d[x] = d[f] + 1;
     62     for(int i = e[x]; i; i = edge[i].nex) {
     63         int y = edge[i].v;
     64         if(y == f) continue;
     65         DFS(y, x);
     66     }
     67     ed[x] = num;
     68     return;
     69 }
     70 
     71 inline void prework() {
     72     for(int i = 2; i <= n; i++) pw[i] = pw[i >> 1] + 1;
     73     for(int j = 1; j <= pw[n]; j++) {
     74         for(int i = 1; i <= n; i++) {
     75             fa[i][j] = fa[fa[i][j - 1]][j - 1];
     76         }
     77     }
     78     return;
     79 }
     80 
     81 inline int lca(int x, int y) {
     82     if(d[x] > d[y]) std::swap(x, y);
     83     int t = pw[n];
     84     while(t >= 0 && d[y] > d[x]) {
     85         if(d[fa[y][t]] >= d[x]) {
     86             y = fa[y][t];
     87         }
     88         t--;
     89     }
     90     if(x == y) return x;
     91     t = pw[n];
     92     while(t >= 0 && fa[x][0] != fa[y][0]) {
     93         if(fa[x][t] != fa[y][t]) {
     94             x = fa[x][t];
     95             y = fa[y][t];
     96         }
     97         t--;
     98     }
     99     return fa[x][0];
    100 }
    101 
    102 inline int getPos(int x, int y) {
    103     int t = pw[n];
    104     while(t >= 0 && fa[y][0] != x) {
    105         if(d[fa[y][t]] > d[x]) {
    106             y = fa[y][t];
    107         }
    108         t--;
    109     }
    110     return y;
    111 }
    112 
    113 void Div(int L, int R, int l, int r) {
    114     if(L > R) return;
    115     if(l == r) {
    116         for(int i = L; i <= R; i++) {
    117             if(node[i].id) ans[node[i].id] = r;
    118         }
    119         return;
    120     }
    121 
    122     int mid = (l + r) >> 1, top1 = 0, top2 = 0, top = 0;
    123     for(int i = L; i <= R; i++) {
    124         int x = node[i].x, y = node[i].y, z = node[i].z;
    125         if(!node[i].id) { /// change  |  this is a Matrix
    126             if(node[i].k > mid) {
    127                 t2[++top2] = node[i];
    128                 continue;
    129             }
    130             t1[++top1] = node[i];
    131             if(z) { /// line
    132                 stk[++top] = Node(1, pos[y], ed[y], 1, 0);
    133                 stk[++top] = Node(pos[z], pos[y], ed[y], -1, 0);
    134                 stk[++top] = Node(pos[y], ed[z] + 1, n, 1, 0);
    135                 stk[++top] = Node(ed[y] + 1, ed[z] + 1, n, -1, 0);
    136             }
    137             else { /// lca
    138                 stk[++top] = Node(pos[x], pos[y], ed[y], 1, 0);
    139                 stk[++top] = Node(ed[x] + 1, pos[y], ed[y], -1, 0);
    140             }
    141         }
    142         else { /// ask  |  this is a Point
    143             stk[++top] = Node(pos[x], 0, pos[y], i, 1);
    144         }
    145     }
    146     std::sort(stk + 1, stk + top + 1);
    147     for(int i = 1; i <= top; i++) {
    148         if(stk[i].z == 0) { /// change
    149             ta::add(stk[i].x, stk[i].k);
    150             ta::add(stk[i].y + 1, -stk[i].k);
    151         }
    152         else { /// ask
    153             int t = ta::ask(stk[i].y), id = stk[i].k;
    154             if(node[id].k <= t) {
    155                 t1[++top1] = node[id];
    156             }
    157             else {
    158                 node[id].k -= t;
    159                 t2[++top2] = node[id];
    160             }
    161         }
    162     }
    163     for(int i = 1; i <= top; i++) { /// clear
    164         if(stk[i].z == 0) {
    165             ta::del(stk[i].x);
    166             ta::del(stk[i].y + 1);
    167         }
    168     }
    169     memcpy(node + L, t1 + 1, top1 * sizeof(Node));
    170     memcpy(node + L + top1, t2 + 1, top2 * sizeof(Node));
    171     Div(L, L + top1 - 1, l, mid);
    172     Div(L + top1, R, mid + 1, r);
    173     return;
    174 }
    175 
    176 int main() {
    177     int m, q;
    178     scanf("%d%d%d", &n, &m, &q);
    179     for(int i = 1, x, y; i < n; i++) {
    180         scanf("%d%d", &x, &y);
    181         add(x, y); add(y, x);
    182     }
    183     DFS(1, 0);
    184     prework();
    185     for(int i = 1, x, y, z; i <= m; i++) {
    186         scanf("%d%d%d", &x, &y, &X[i]);
    187         if(pos[x] > pos[y]) std::swap(x, y);
    188         z = lca(x, y);
    189         node[i] = Node(0, x, y, X[i], (z == x) ? getPos(x, y) : 0);
    190     }
    191     std::sort(X + 1, X + n + 1);
    192     xx = std::unique(X + 1, X + n + 1) - X - 1;
    193     for(int i = 1; i <= m; i++) {
    194         node[i].k = std::lower_bound(X + 1, X + xx + 1, node[i].k) - X;
    195     }
    196     for(int i = 1, x, y, k; i <= q; i++) {
    197         scanf("%d%d%d", &x, &y, &k);
    198         if(pos[x] > pos[y]) std::swap(x, y);
    199         node[m + i] = Node(i, x, y, k, 0);
    200     }
    201     Div(1, m + q, 1, xx);
    202     for(int i = 1; i <= q; i++) printf("%d
    ", X[ans[i]]);
    203     return 0;
    204 }
    AC代码
  • 相关阅读:
    2019春总结作业
    第二周作业
    第三周作业
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
    2019春第一次课程设计实验报告
    第十二周作业
    第十一周作业
    第十周作业
    第九周作业
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10485234.html
Copyright © 2011-2022 走看看