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 }
  • 相关阅读:
    Azure PowerShell (2) 修改Azure订阅名称
    Windows Azure Platform Introduction (11) 了解Org ID、Windows Azure订阅、账户
    Azure PowerShell (3) 上传证书
    Azure PowerShell (1) PowerShell入门
    Windows Azure Service Bus (2) 队列(Queue)入门
    Windows Azure Service Bus (1) 基础
    Windows Azure Cloud Service (10) Role的生命周期
    Windows Azure Cloud Service (36) 在Azure Cloud Service配置SSL证书
    Android studio 使用心得(一)—android studio快速掌握快捷键
    android 签名、混淆打包
  • 原文地址:https://www.cnblogs.com/dirge/p/5998729.html
Copyright © 2011-2022 走看看