zoukankan      html  css  js  c++  java
  • 【2016东北四省赛】

    HDU5925

    题意:给出一个R*C(R, C <= 1e9)的地图,地图上有n(n <= 200)个点的障碍,其余为空地。问有多少个四连通图以及各个四连通图的大小。

    题解:离散化。将x, y坐标分别离散化。对于xi点再插入xi-1, xi+1两个点。

    则离散化后的权值大小为xi-xi-1.对y作同样处理。处理完毕后bfs图,空白格的面积为x对应权值与y对应权值之积。

    Time: 0ms

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define gg puts("gg");
     4 using namespace std;
     5 int ma[666][666];
     6 int xma[666], yma[666];
     7 int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}, X, Y;
     8 void dfs(int x, int y, ll& ret){
     9     if(!ma[x][y]){
    10         ret += xma[x]*(ll)yma[y];
    11         ma[x][y] = 1;
    12         for(int i = 0; i < 4; i++){
    13             int xi = x+dx[i], yi = y+dy[i];
    14             dfs(xi, yi, ret);
    15         }
    16     }
    17 }
    18 int x[222], y[222];
    19 
    20 int main(){
    21     int t, ca = 1; scanf("%d", &t);
    22     while(t--){
    23         printf("Case #%d:
    ", ca++);
    24         int r, c, n; scanf("%d%d", &r, &c);
    25         scanf("%d", &n);
    26         vector<int> xx, yy;
    27         xx.push_back(0), xx.push_back(r), xx.push_back(r+1);
    28         yy.push_back(0), yy.push_back(c), yy.push_back(c+1);
    29         for(int i = 0; i < n; i++){
    30             scanf("%d%d", x+i, y+i);
    31             for(int j = -1; j <= 1; j++)
    32                 xx.push_back(x[i]+j), yy.push_back(y[i]+j);
    33         }
    34         sort(xx.begin(), xx.end());
    35         xx.erase(unique(xx.begin(), xx.end()), xx.end());
    36         xma[0] = 1;
    37         for(int i = 1; i < xx.size(); i++)
    38             xma[i] = xx[i]-xx[i-1];
    39         sort(yy.begin(), yy.end());
    40         yy.erase(unique(yy.begin(), yy.end()), yy.end());
    41         yma[0] = 1;
    42         for(int i = 1; i < yy.size(); i++)
    43             yma[i] = yy[i]-yy[i-1];
    44 
    45         memset(ma, 0, sizeof(ma));
    46         for(int i = 0; i < n; i++){
    47             int a = lower_bound(xx.begin(), xx.end(), x[i])-xx.begin();
    48             int b = lower_bound(yy.begin(), yy.end(), y[i])-yy.begin();
    49             ma[a][b] = 1;
    50         }
    51         int rr = xx.size(), cc = yy.size();
    52         for(int i = 0; i < cc; i++)
    53             ma[0][i] = ma[rr-1][i] = 1;
    54         for(int i = 0; i < rr; i++)
    55             ma[i][0] = ma[i][cc-1] = 1;
    56 
    57         vector<ll> ans;
    58         for(int i = 1; i < rr; i++)
    59             for(int j = 1; j < cc; j++)
    60                 if(!ma[i][j]) {
    61                     ll ret = 0;
    62                     dfs(i, j, ret);
    63                     ans.push_back(ret);
    64                 }
    65         sort(ans.begin(), ans.end());
    66         int tot = ans.size();
    67         printf("%d
    ", tot);
    68         for(int i = 0; i < tot; i++)
    69             printf("%lld%c", ans[i], " 
    "[i == tot-1]);
    70     }
    71     return 0;
    72 }

    ********************************************************************

    HDU5927

    题意:给出一个根节点为1的树(n <= 100000),树中的结点分为重要结点与不重要结点。

    有q个询问,每次询问给出一个不重要结点的集合(m <= 100000), 统计一类点(它是重要结点 或者 它是两个重要结点的最近公共祖先) 的总数。

    题解:

    1372MS: dfs, 子结点不是集合中的点时直接return,否则递归dfs.

    Time: 1372MS

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e5+10;
     4 vector<int> ve[N];
     5 int fa[N], n, m, ans;
     6 int temp[N], vis[N];
     7 int dfs(int f, int x){
     8     fa[x] = f;
     9     for(int i = 0; i < ve[x].size(); i++){
    10         int y = ve[x][i];
    11         if(y == f) continue ;
    12         dfs(x, y);
    13     }
    14 }
    15 int dfs2(int f, int x, int pos){
    16     int num = 0;
    17     for(int i = 0; i < ve[x].size()&&num < 2; i++){
    18         int y = ve[x][i];
    19         if(y == f) continue ;
    20         int ppos = lower_bound(temp, temp+m, y)-temp;
    21         if(ppos >= m||temp[ppos] != y||vis[ppos] > 0) num++;
    22         else if(vis[ppos] == -1&&dfs2(x, y, ppos) > 0)
    23             num++;
    24     }
    25     if(num > 1) ans++;
    26     return vis[pos] = num;
    27 }
    28 
    29 int main(){
    30     int t, ca = 1; scanf("%d", &t);
    31     while(t--){
    32         int q, u, v; scanf("%d%d", &n, &q);
    33         for(int i = 1; i < n; i++){
    34             scanf("%d%d", &u, &v);
    35             ve[u].push_back(v);
    36             ve[v].push_back(u);
    37         }
    38         dfs(0, 1);
    39         printf("Case #%d:
    ", ca++);
    40         while(q--){
    41             scanf("%d", &m);
    42             for(int i = 0; i < m; i++)
    43                 scanf("%d", temp+i);
    44             sort(temp, temp+m);
    45             memset(vis, -1, sizeof(int)*(m+1));
    46             ans = 0;
    47             for(int i = 0; i < m; i++) if(vis[i] == -1)
    48                 dfs2(fa[temp[i]], temp[i], i);
    49             printf("%d
    ", n-m+ans);
    50         }
    51         for(int i = 1; i <= n; i++)
    52             ve[i].clear();
    53     }
    54     return 0;
    55 }

    1794MS: 维护一个set集合表示以该结点为根的子树不含重要结点,set集合初始即为m个点。按 后序遍历 将集合中的点排序后(ra表示结点后序遍历中的排名),对每个点,查找子结点点,若至少有两个子结点不在set里,则该点是可行点,同时将其从集合中删除。

    复杂度分析:每次询问的复杂度为O(mlogm)

    Time: 1794MS

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e5+10;
     4 vector<int> ve[N];
     5 int ra[N], tot;
     6 void dfs(int f, int x){
     7     for(int i = 0; i < ve[x].size(); i++){
     8         int y = ve[x][i];
     9         if(y == f) continue ;
    10         dfs(x, y);
    11     }
    12     ra[x] = tot++;
    13 }
    14 bool cmp(int a, int b){
    15     return ra[a] < ra[b];
    16 }
    17 
    18 
    19 int temp[N];
    20 int tag[N];
    21 int main(){
    22     int t, ca = 1; scanf("%d", &t);
    23     while(t--){
    24         int n, q, u, v; scanf("%d%d", &n, &q);
    25         for(int i = 1; i < n; i++){
    26             scanf("%d%d", &u, &v);
    27             ve[u].push_back(v);
    28             ve[v].push_back(u);
    29         }
    30         tot = 0;
    31         dfs(0, 1);
    32         printf("Case #%d:
    ", ca++);
    33         while(q--){
    34             int m, x; scanf("%d", &m);
    35             for(int i = 0; i < m; i++)
    36                 scanf("%d", temp+i);
    37             sort(temp, temp+m, cmp);
    38             set<int> se;
    39             for(int i = 0; i < m; i++)
    40                 se.insert(temp[i]);
    41             int ans = 0;
    42             for(int i = 0; i < m; i++){
    43                 int x = temp[i], sum = 0;
    44                 for(int j = 0; j < ve[x].size(); j++){
    45                     int y = ve[x][j];
    46                     if(ra[y] > ra[x]) continue;
    47                     if(se.find(y) == se.end()){
    48                         sum++;
    49                         if(sum > 1){
    50                             ans++;
    51                             break;
    52                         }
    53                         se.erase(x);
    54                     }
    55                 }
    56             }
    57             printf("%d
    ", n-m+ans);
    58         }
    59         for(int i = 1; i <= n; i++)
    60             ve[i].clear();
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    Windows Phone 7 电话本相关的操作
    Windows CE 下判断 URL 地址是否有效
    cigarettes
    开灯问题
    日期计算
    小学生算术
    另一种阶乘问题
    鸡兔同笼
    笨小熊
    6174问题
  • 原文地址:https://www.cnblogs.com/dirge/p/5998729.html
Copyright © 2011-2022 走看看