• 个人比赛总结(坑


    存题处 

    /******************/ 

    为了迎接社会主义现代化建设所必须要的技术:

    1、尺取法

    2、反转法

    3、弹性碰撞

    4、折半枚举

    5、坐标离散化

     

    一、动规

    1.概率dp

    URAL 1776 Anniversary Firework

    思路:此题直接求期望太过复杂。因为期望等于所有可能答案的概率与该答案的值的乘积的累加和,所以,我们可以求对于每个可能答案的概率,由此简化问题。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <vector>
     4 #include <cstring>
     5 
     6 const int N = 400 + 10;
     7 double d[N][N], sum[N][N];
     8 
     9 int main() {
    10     int n;
    11     scanf("%d", &n);
    12     n -= 2;
    13 
    14     memset(d, 0sizeof d);
    15     memset(sum, 0sizeof sum);
    16 
    17     d[0][0] = 1.;
    18     for (int j = 0; j <= n; ++j)
    19         sum[0][j] = 1.;
    20 
    21     for (int i = 1; i <= n; ++i) {
    22         for (int j = 0; j <= i - 1; ++j) {
    23             int l = j, r = i - 1 - j;
    24             int t = std::max(l, r) + 1;
    25 
    26             for (int k = 1; k <= t; ++k) {
    27                 d[i][k] += (d[l][k - 1] * sum[r][k - 1] + d[r][k - 1] * sum[l][k - 1] - d[l][k - 1] * d[r][k - 1]) / i;
    28             }
    29 
    30             for (int j = 1; j <= n; ++j)
    31                 sum[i][j] = sum[i][j - 1] + d[i][j];
    32         }
    33     }
    34 
    35     double ans = 0;
    36     for (int j = 1; j <= n; ++j)
    37         ans = ans + d[n][j] * j * 10;
    38 
    39     printf("%.8f ", ans);
    40     return 0;
    41 }
    View Code 

    2.树形dp 

    CodeForces 208B Solitaire 

    题意:n张牌,如果第i张牌与第i-1或者第i-3张牌花色一样或者数字一样,那么可以将这两张牌合并,合并后,第i张牌覆盖合并的牌。

    问将n张牌合并成一张牌是否可能。n <=52。 

    思路:dp(i,a,b,c)//前i张牌,第i张是c,第i-1张是b,第i-2张是c时是否可以合并成功

    3.朴素dp

    二、图论 

    1.最短路

    2.网络流

    URAL 1774 Barber of the Army of Mages

    三、数据结构

    1.并查集 

    SGU 336 Elections

    2.树状数组

    UVA 12429 Finding Magic Triplets

    题意:对于给定的n和K,要求满足a+b*b=c*c*c(mod K) ——(1<=a<=b<=c<=n)的组合数

    方法:我们发现,当我们固定b的时候,左侧是一个连续的区间,我们可以预先将右侧的值存入树状数组,然后询问区间和即可。

    要注意把握连续区间这一特点,还有固定中间值这个方法 

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 typedef long long ll;
     5 #define lson l, mid, rt << 1
     6 #define rson mid + 1, r, rt << 1 | 1
     7 const int N = 100000 + 10;
     8 int T = 0;
     9 
    10 ll sum[N];
    11 int K;
    12 
    13 void add(int pos, ll v) {
    14     if (pos == 0) sum[0] += v;
    15     else {
    16         for (;pos < K; pos += pos & -pos)
    17             sum[pos] += v;
    18     }
    19 }
    20 ll query(int pos) {
    21     if (pos < 0return 0;
    22     else {
    23         ll re = sum[0];
    24         for (;pos > 0; pos -= pos & -pos)
    25             re += sum[pos];
    26         return re;
    27     }
    28 }
    29 inline ll Q(int L, int R) {
    30     return query(R) - query(L - 1);
    31 }
    32 void work() {
    33     int n;
    34     memset(sum, 0sizeof(ll) * K);
    35     scanf("%d%d", &n, &K);
    36 
    37     int l, r, v;
    38     ll ans = 0;
    39     for (int b = n; b >= 1; --b) {
    40         v = (ll)b * b * b % K;
    41         add(v, 1);
    42 
    43         v = (ll)b * b % K;
    44         if (K > b) {
    45             l = 1; r = b;
    46             l = (l + v) % K; r = (r + v) % K;
    47             if (r < l) {
    48                 ans += Q(0, r) + Q(l, K - 1);
    49             } else {
    50                 ans += Q(l, r);
    51             }
    52         } else {
    53             l = 0; r = K - 1;
    54             l = (l + v) % K; r = (r + v) % K;
    55             if (r < l) {
    56                 ans += Q(0, r) * (b / K) + Q(l, K - 1) * (b / K);
    57             } else {
    58                 ans += Q(l, r) * (b / K);
    59             }
    60             if (b % K > 0) {
    61                 l = 1; r = b % K;
    62                 l = (l + v) % K; r = (r + v) % K;
    63                 if (r < l) {
    64                     ans += Q(0, r) + Q(l, K - 1);
    65                 } else {
    66                     ans += Q(l, r);
    67                 }
    68             }
    69         }
    70     }
    71 
    72     printf("Case %d: %lld ", ++ T, ans);
    73 }
    74 int main() {
    75     int cas;
    76     scanf("%d", &cas);
    77     while (cas -- > 0) {
    78         work();
    79     }
    80     return 0;
    81 }
    View Code 

    1990 MooFest

    题意:给定n个pair型,对于每一对pair型,ans+=max(a.first,b.first) * abs(a.second - b.second),求最后的结果。

    思路:按照first排序,然后树状数组维护

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 const int N = 200000 + 10;
     5 typedef long long ll;
     6 struct node {
     7     int pos;
     8     ll v;
     9 };
    10 
    11 node ar[N];
    12 
    13 struct Bit {
    14     ll sum[N];
    15     void clear() {
    16         memset(sum, 0sizeof sum);
    17     }
    18     void add(int pos, ll v) {
    19         if (pos == 0) sum[0] += v;
    20         else {
    21             for (;pos < N; pos += pos & -pos)
    22                 sum[pos] += v;
    23         }
    24     }
    25     ll query(int pos) {
    26         if (pos < 0return 0;
    27         else {
    28             ll re = sum[0];
    29             for (;pos > 0; pos -= pos & -pos)
    30                 re += sum[pos];
    31             return re;
    32         }
    33     }
    34 };
    35 
    36 Bit a, b;
    37 int n;
    38 
    39 bool cmp(const node& a, const node&  b) {
    40     return a.v < b.v;
    41 }
    42 void work() {
    43     a.clear(); b.clear();
    44 
    45     for (int i = 0; i < n; ++i)
    46         scanf("%d%d", &ar[i].v, &ar[i].pos);
    47 
    48     std::sort(ar, ar + n, cmp);
    49 
    50     ll ans = 0, tot = 0;
    51     for (int i = 0; i < n; ++i) {
    52         ll w = a.query(ar[i].pos);
    53         ll n1 = b.query(ar[i].pos);
    54 
    55         ans += (n1 * ar[i].pos - w) * ar[i].v + (tot - w - (i - n1) * ar[i].pos) * ar[i].v;
    56 //        printf("%lld ", ans);
    57         a.add(ar[i].pos, ar[i].pos);
    58         b.add(ar[i].pos, 1);
    59 
    60         tot = tot + ar[i].pos;
    61     }
    62 
    63     printf("%lld ", ans);
    64 }
    65 int main() {
    66     while (1 == scanf("%d", &n)) {
    67         work();
    68     }
    69     return 0;
    70 }
    View Code 

    poj 3109 Inner Vertices

    题意:给100000个黑色点,如果两对点的连线相交于一个白色点,则此点变成黑色。问最终会有多少个点。

    思路:扫描线。

    预处理:1,离散化坐标 2,找出所有最长垂直线段和水平线段 3,垂直线段按照x轴坐标分类 4,水平线段按照起点x轴坐标分类(3,4的线段放入vector中)

    核心:1,枚举所有横坐标x,将所有起点坐标>=x的水平线段加入(在树状数组中更新其y坐标) 2,将所有终点坐标<x的水平线段删除(用优先队列维护,队首是终点最小;同时更新树状数组) 3,此时树状数组中所有的y值对应的水平线段都是横跨垂直线段x的,更新答案。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <queue>
      6 typedef std::pair<intint> pii;
      7 const int INF = (int)(1e9) + 10;
      8 const int N = 100000 + 10;
      9 
     10 int X[N], idx, Y[N], idy;
     11 
     12 pii p[N];
     13 int n;
     14 
     15 std::vector<int> ar[N];
     16 std::vector<pii> b[N];
     17 int bra[N], brb[N];
     18 
     19 int sum[N];
     20 
     21 struct node {
     22     int x, y;
     23     node() {};
     24     node(int _x, int _y) {
     25         x = _x, y = _y;
     26     }
     27     friend bool operator < (const node& a, const node& b) {
     28         return a.x > b.x;
     29     }
     30 };
     31 std::priority_queue<node> Q;
     32 
     33 int t[N];
     34 
     35 void add(int pos, int v) {
     36     if (0 == pos) sum[0] += v;
     37     else {
     38         for (int i = pos; i < idy; i += i & -i)
     39             sum[i] += v;
     40     }
     41 }
     42 int query(int pos) {
     43     if (pos < 0return 0;
     44     int re = sum[0];
     45     for (int i = pos; i > 0; i -= i & -i)
     46         re += sum[i];
     47     return re;
     48 }
     49 
     50 inline int Qu(int L, int R) {
     51     return query(R) - query(L - 1);
     52 }
     53 void work() {
     54     for (int i = 0; i < n; ++i) {
     55         scanf("%d%d", &p[i].first, &p[i].second);
     56         X[i] = p[i].first; Y[i] = p[i].second;
     57     }
     58     std::sort(X, X + n); std::sort(Y, Y + n);
     59     idx = std::unique(X, X + n) - X; idy = std::unique(Y, Y + n) - Y;
     60 
     61     for (int i = 0; i < n; ++i) {
     62         p[i].first = std::lower_bound(X, X + idx, p[i].first) - X;
     63         p[i].second = std::lower_bound(Y, Y + idy, p[i].second) - Y;
     64     }
     65     //求出所有 垂直线
     66     for (int i = 0; i < idx; ++i) ar[i].clear();
     67     for (int i = 0; i < n; ++i)
     68         ar[p[i].first].push_back(p[i].second);
     69     for (int i = 0; i < idx; ++i)
     70         std::sort(ar[i].begin(), ar[i].end()); //a[x] (y1, y2)
     71 
     72     memset(brb, -1sizeof brb);
     73     std::fill(bra, bra + idy + 1, INF);
     74 
     75     for (int i = 0; i < n; ++i) {
     76         bra[p[i].second] = std::min(bra[p[i].second], p[i].first);
     77         brb[p[i].second] = std::max(brb[p[i].second], p[i].first);
     78     }
     79 
     80     for (int i = 0; i < idx; ++i) b[i].clear();
     81     for (int i = 0; i < idy; ++i)
     82     if (bra[i] < brb[i]) {
     83         b[bra[i]].push_back(pii(brb[i], i)); //b[x1] (x2, y)
     84     }
     85 
     86     while (!Q.empty()) Q.pop();
     87     memset(sum, 0sizeof sum);
     88     memset(t, 0sizeof t);
     89 
     90     int ans = 0;
     91     for (int i = 0; i < idx; ++i) {
     92         for (int j = 0; j < b[i].size(); ++j) {
     93             add(b[i][j].second, 1);
     94             ++ t[b[i][j].second];
     95             Q.push(node(b[i][j].first, b[i][j].second)); //(edx, y)
     96         }
     97         while (!Q.empty() && Q.top().x < i) {
     98             add(Q.top().y, -1);
     99             -- t[Q.top().y];
    100             Q.pop();
    101         }
    102         if (ar[i].size() > 1) {
    103             ans += Qu(ar[i][0], ar[i][ar[i].size() - 1]);
    104             for  (int j = 0; j < ar[i].size(); ++j) {
    105                 if (0 == t[ar[i][j]])
    106                     ++ ans;
    107             }
    108         } else {
    109             ans += ar[i].size();
    110         }
    111 
    112     }
    113     printf("%d ", ans);
    114 }
    115 int main() {
    116     while (1 == scanf("%d", &n)) {
    117         work();
    118     }
    119     return 0;
    120 }
    View Code

    四、贪心

    POJ 2698 Servicing DVD Requests

    五、数论

    1.辗转相除法及其拓展应用

    填数游戏

    题意:p1(x1,y1)到p2(x2,y2)的线段上有多少个格点(x,y皆为整数) 

    思路:gcd(x2-x1,y2-y1) - 1代表不连p1,p2时的答案。

    x=x2-x1,y=y2-y1 ,假设答案是g,那么x,y都要可以整除g。所以g最大就是gcd(x,y)。

    2.高斯消元

    hdu 2262 Where is the canteen

    http://blog.csdn.net/acm_cxlove/article/details/7905778

    基础的高斯求概率。

    设某点的期望步数为Ei。

    那么目标的Ei=0。

    Ei=(Enext1+Enext2……Enextk)/k+1。

    整理下就是Enext1+Enext2……Enextk-k*Ei=-k

    根据i点的后继结点nextj,那么从所有的后继结点走一步都可以到达i点。便是所有后继的期望平均值+1.

    以此建立方程组,然后用高斯消元求解。

      1 #include <cstring>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <cmath>
      6 
      7 typedef std::vector<double> vec;
      8 typedef std::vector<vec> mat;
      9 const double eps = 1e-8;
     10 
     11 vec gauss_jordan(const mat& A, const vec& b) {
     12     int n = A.size();
     13     mat B(n, vec(n + 1));
     14     for(int i = 0; i < n; ++i)
     15         for (int j = 0; j < n; ++j)
     16             B[i][j] = A[i][j];
     17     for (int i = 0; i < n; ++i) B[i][n] = b[i];
     18 
     19     for (int i = 0; i < n; ++i) {
     20         int pivot = i;
     21         for (int j = i; j < n; ++j) {
     22             if (abs(B[j][i]) > abs(B[pivot][i])) pivot = j;
     23         }
     24         std::swap(B[i], B[pivot]);
     25 
     26         //有无穷解或者无解
     27         if (abs(B[i][i]) < eps) return vec();
     28 
     29         //吧正在处理的未知数的系数变成1
     30         for (int j = i + 1; j <= n; ++j) B[i][j] /= B[i][i];
     31         for (int j = 0; j < n ;++j) {
     32             if (i != j) {
     33                 for (int k = i + 1; k <= n; ++k)
     34                     B[j][k] -= B[j][i] * B[i][k];
     35             }
     36         }
     37     }
     38     vec x(n);
     39     for (int i = 0; i < n; ++i) x[i] = B[i][n];
     40     return x;
     41 }
     42 
     43 const int dx[] = {10, -10};
     44 const int dy[] = {010, -1};
     45 const int M = 15 + 1;
     46 
     47 char s[M][M];
     48 bool vis[M][M];
     49 
     50 int r, c;
     51 
     52 void dfs(int x, int y) {
     53     vis[x][y] = true;
     54     for (int dir = 0; dir < 4; ++dir) {
     55         int nx = x + dx[dir], ny = y + dy[dir];
     56         if (nx >= 0 && nx < r && ny >= 0 && ny < c && !vis[nx][ny]) {
     57             if (s[nx][ny] == '.')
     58                 dfs(nx, ny);
     59             else if (s[nx][ny] == '$')
     60                 vis[nx][ny] = true;
     61         }
     62     }
     63 }
     64 void work() {
     65     int sx, sy;
     66     for (int i = 0; i < r; ++i) {
     67         scanf("%s", s[i]);
     68         for (int j = 0; j < c; ++j)
     69         if (s[i][j] == '@') {
     70             sx = i; sy = j;
     71         }
     72     }
     73 
     74     memset(vis, 0sizeof vis);
     75 //    printf("%d %d ", sx, sy);
     76     dfs(sx, sy);
     77 
     78     bool f = false;
     79     for (int i = 0; i < r; ++i)
     80         for (int j = 0; j < c; ++j)
     81             if (s[i][j] == '$' && vis[i][j])
     82                 f = true;
     83     if (f) {
     84         mat A(r * c, vec(r *c, 0));
     85         vec b(r * c, 0);
     86 
     87         for (int i = 0; i < r; ++i)
     88         for (int j = 0; j < c; ++j) {
     89             if (s[i][j] == '$' || !vis[i][j]) {
     90                 A[i * c + j][i * c + j] = 1;
     91                 continue;
     92             }
     93 
     94             int moves = 0;
     95             for (int dir = 0; dir < 4; ++dir) {
     96                 int nx = i + dx[dir], ny = j + dy[dir];
     97                 if (nx >= 0 && nx < r && ny >= 0 && ny < c && vis[nx][ny]) {
     98                     ++moves;
     99                     A[i * c + j][nx * c + ny] = -1;
    100                 }
    101             }
    102             b[i * c + j] = A[i * c + j][i * c + j] = moves;
    103         }
    104         vec x = gauss_jordan(A, b);
    105         if (x.size() > 0 && fabs(x[sx * c + sy]) > eps) {
    106             printf("%.6f ", x[sx * c + sy]);
    107         } else {
    108             puts("-1");
    109 //            printf("%.6f ", x[sx * c + sy]);
    110         }
    111     } else {
    112         puts("-1");
    113     }
    114 }
    115 int main() {
    116     while (2 == scanf("%d%d", &r, &c)) {
    117         work();
    118     }
    119     return 0;
    120 }
    121 
    122 
    123 int q(n, m) {
    124     if (m == 1return 1;
    125     else if (m > n) return q(n, n);
    126     else return q(n, m - 1) + q(n - m, m);
    127 }
    View Code 

    /******************************华丽的分割线*******************************************/ 

    炫酷算术魔法结社群赛系列(群号283513414)(举办者  ftiasch)

    20130926 - 初级魔法练习

    A:POJ 2443 Set Operation

    题意:给我一个1000行,10000列的01矩阵,对于指定两列询问是否存在公共的1。

    方法:压缩。对于给定两列,如果直接比较需要枚举1000位,我们可以每30位压缩成一个数,用二进制&运算代替枚举,则枚举次数就变成了1000/30 <= 34,起到了非凡的加速效果。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 
     5 const int N = 10000;
     6 const int M = 35;
     7 int b[N + 1][M];
     8 
     9 int n;
    10 
    11 bool check(int x, int y) {
    12     for (int i = 0; i < M; ++i)
    13         if ((b[x][i] & b[y][i]) > 0return true;
    14     return false;
    15 }
    16 void work() {
    17     memset(b, 0sizeof(b));
    18 
    19     int u, v;
    20     for (int i = 0; i < n; ++i) {
    21         scanf("%d", &u);
    22         while (u -- > 0) {
    23             scanf("%d", &v);
    24             b[v][i / 30] |= 1 << (i % 30);
    25         }
    26     }
    27     int Q, x, y;
    28     scanf("%d", &Q);
    29     while (Q -- > 0) {
    30         scanf("%d%d", &x, &y);
    31         if (check(x, y))
    32             puts("Yes");
    33         else
    34             puts("No");
    35     }
    36 }
    37 int main() {
    38     while (1 == scanf("%d", &n)) {
    39         work();
    40     }
    41     return 0;
    42 }
    View Code 

    B:POJ 3244 Difference between Triplets

     

    关于这个公式的解释,我们可以将I,J,K看成图上三个点,那么max{I, J, K} - min{I, J, K}就是一条线段的距离然后线性扫描即可。 

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 typedef long long ll;
     5 const int N = 200000;
     6 
     7 int ab[N], ac[N], bc[N];
     8 
     9 int n;
    10 
    11 void gao(ll& sum, int* num) {
    12     for (int i = 1; i < n; ++i) {
    13         sum = sum + (ll)(n - i) * i * (num[i] - num[i - 1]);
    14     }
    15 }
    16 void work() {
    17     int a, b, c;
    18     for (int i = 0; i < n; ++i) {
    19         scanf("%d%d%d", &a, &b, &c);
    20         ab[i] = a - b; ac[i] = a - c; bc[i] = b - c;
    21     }
    22 
    23     std::sort(ab, ab + n);
    24     std::sort(bc, bc + n);
    25     std::sort(ac, ac + n);
    26 
    27     ll sum = 0;
    28     gao(sum, ab);
    29     gao(sum, ac);
    30     gao(sum, bc);
    31 
    32     printf("%lld ", sum / 2);
    33 }
    34 int main() {
    35     while (1 == scanf("%d", &n)) {
    36         if (0 == n) break;
    37         work();
    38     }
    39     return 0;
    40 }
    View Code 

    20130929 - 火球术入门

    A:POJ 3040 Allowance
    B:POJ 3182 The Grove

    20130930 - 风系魔法的基本要领

    B:poj 3375 Network Connection

    题意:有n台电脑,m个接口,每台电脑和接口都有属于自己的一维坐标,每个电脑都要选择一个接口连接,连接的代价是|Xi - Yj|。

    n <= 2000, m <= 100000;

    思路:首先O(N*M)的dp肯定可以轻松想到,d[i][j]//用前j个接口来满足前i台电脑后最小需要花费多少

    这个算法复杂度太高,所以我们将它优化。我们先在Y中找最接近Xi的那个接口p,对于Xi这才是最佳答案,但是,他可能被其他接口占用,最多有n个接口会占用他,所以,上限是p+n,这个接口也可能要留给其他的接口用,所以,最多有n个接口在后面等着用这个接口,下限是p-n。由此,算法优化到了O(N^2)

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <cmath>
     5 typedef long long ll;
     6 const ll INF = 1ll << 60;
     7 
     8 const int N = 2000 + 10;
     9 const int M = 100000 + 10;
    10 
    11 ll d[N][N << 1];
    12 
    13 int L[N], R[N];
    14 int n, m;
    15 
    16 int x[N], y[M];
    17 
    18 void work() {
    19     for (int i = 1; i <= m; ++i)
    20         scanf("%d", &y[i]);
    21     for (int i = 1; i <= n; ++i)
    22         scanf("%d", &x[i]);
    23 
    24     std::sort(x + 11 + x + n);
    25     std::sort(y + 11 + y + m);
    26 
    27     for (int i = 1; i <= n; ++i) {
    28         int p = std::lower_bound(y + 1, y + m + 1, x[i]) - y;
    29         L[i] = std::max(1, p - n);
    30         R[i] = std::min(m, p + n);
    31     }
    32 
    33     for (int i = 0; i < N + N; ++i) d[1][i] = INF;
    34     for (int i = L[1]; i <= R[1]; ++i) d[1][i - L[1]] = abs(x[1] - y[i]);
    35 
    36     for (int i = 2; i <= n; ++i) {
    37         int k = L[i - 1];
    38         ll v = INF;
    39 
    40         for (int j = L[i]; j <= R[i]; ++j) {
    41             while (k <= R[i - 1] && k < j) {
    42                 v = std::min(v, d[i - 1][k - L[i - 1]]);
    43                 ++k;
    44             }
    45             d[i][j - L[i]] = std::min(INF, v + std::abs(x[i] - y[j]));
    46             // printf("%d %d %d ", x[i], y[j], d[i][j]);
    47         }
    48     }
    49     ll mx = INF;
    50     for (int i = L[n]; i <= R[n]; ++i)
    51         mx = std::min(mx, d[n][i - L[n]]);
    52 
    53     printf("%I64d ", mx);
    54 }
    55 int main() {
    56     while (2 == scanf("%d%d", &m, &n)) {
    57         work();
    58     }
    59     return 0;
    60 }
    View Code 

    C:poj 3419 Difference Is Beautiful

    20131001 - 我是如何成为一名合格的小学生的?

    A:HDU 3552 I can do it!

    题意:给我n个pair型元素,要求我们把他们分成两组(A,B两组),使得A组中first元素的最大值+B组中second元素的最大值的和最小

    思路:按照first的值排序,然后枚举A组最大值,线性扫描即可

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 typedef std::pair<intint> pii;
     5 int T = 0;
     6 
     7 const int N = 100000 + 10;
     8 pii ar[N];
     9 
    10 void work() {
    11     int n;
    12     scanf("%d", &n);
    13     for (int i = 0; i < n; ++i) {
    14         scanf("%d%d", &ar[i].first, &ar[i].second);
    15     }
    16 
    17     std::sort(ar, ar + n);
    18 
    19     int ans = (int)(1e9) * 2 + 1;
    20     int bmax = 0;
    21     for (int i = n - 1; i >= 0; --i) {
    22 //        printf("%d ", ans);
    23         ans = std::min(ans, ar[i].first + bmax);
    24         bmax = std::max(bmax, ar[i].second);
    25     }
    26     printf("Case %d: %d ", ++T, ans);
    27 }
    28 int main() {
    29     int cas;
    30     scanf("%d", &cas);
    31     while (cas -- > 0) {
    32         work();
    33     }
    34     return 0;
    35 }
    View Code 

    B:HDU 3545 Board Coloring

    题意:用0到255对一个4*N的格子染色,给定M组限制,对于(x1,y1,x2,y2),必须满足(x1,y1)和(x2,y2)两个格子的颜色一样,问有多少种染色方法。(N<=15)

    思路:很神奇的dp题。因为要求x,y >= A x,y-1所以符合单调性。

    d[x1][x2][x3][x4]//第一行已经染色了前x1格,第二行..

    我们可以先预处理所有不可行的方案,然后每次更新后将这些情况的数值设置为0。

    首先第一层是当前要涂的颜色。第二层表示当前要涂的行,从第1行到第4行。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <vector>
     5 #define REP(i, st, ed) for (i = st; i <= ed; ++i)
     6 const int mod = 100000;
     7 const int N = 15 + 1;
     8 const int M = 100 + 1;
     9 
    10 int d[N][N][N][N];
    11 bool legal[N][N][N][N];
    12 
    13 int x1[M], x2[M], y1[M], y2[M];
    14 int n, m, t = 0;
    15 
    16 int p[4], to[4];
    17 void prepare() {
    18     int i;
    19 
    20     REP(p[0], 0, n)
    21     REP(p[1], 0, n)
    22     REP(p[2], 0, n)
    23     REP(p[3], 0, n){
    24         legal[p[0]][p[1]][p[2]][p[3]] = false;
    25         REP(i, 1, m) {
    26             if ((p[x1[i]] >= y1[i]) ^ (p[x2[i]] >= y2[i])) {
    27                 legal[p[0]][p[1]][p[2]][p[3]] = truebreak;
    28             }
    29         }
    30     }
    31 }
    32 void work() {
    33     scanf("%d%d", &n, &m);
    34     for (int i = 1; i <= m; ++i) {
    35         scanf("%d%d%d%d", &x1[i], &y1[i], &x2[i], &y2[i]);
    36         --x1[i]; --x2[i];
    37     }
    38 
    39     prepare();
    40 
    41     memset(d, 0sizeof d);
    42     d[0][0][0][0] = 1;
    43 
    44     for (int i = 1; i <= 256; ++i) {
    45         for (int idx = 0; idx < 4; ++idx)
    46         REP(p[0], 0, n)
    47         REP(p[1], 0, n)
    48         REP(p[2], 0, n)
    49         REP(p[3], 0, n)
    50         if (d[p[0]][p[1]][p[2]][p[3]] > 0 && p[idx] + 1 <= n) {
    51             ++p[idx];
    52             int& t = d[p[0]][p[1]][p[2]][p[3]];
    53             --p[idx];
    54             t += d[p[0]][p[1]][p[2]][p[3]];
    55             if (t >= mod)
    56                 t -= mod;
    57         }
    58         REP(p[0], 0, n)
    59         REP(p[1], 0, n)
    60         REP(p[2], 0, n)
    61         REP(p[3], 0, n)
    62         if (legal[p[0]][p[1]][p[2]][p[3]])
    63             d[p[0]][p[1]][p[2]][p[3]] = 0;
    64     }
    65     printf("Case %d: %05d ", ++t, d[n][n][n][n]);
    66 }
    67 int main() {
    68     int cas;
    69     scanf("%d", &cas);
    70     while (cas -- > 0) {
    71         work();
    72     }
    73     return 0;
    74 }
    View Code 

    C:HDU 4014 Jimmy’s travel plan

     20131002 - 暴雨术入门

    A:HDU 4103 Clock

    B:HDU 4104 Discount

    C:HDU 4107 Gangster

    20131003 - 在沙漠中的长途旅行

    A:POJ 2793 Cactus

    B:POJ 3567 Cactus Reloaded

    20130904 - 幽默术

    A:POJ 3538 Domestic Networks

    B:POJ 3566 Building for UN

    C:POJ 3537 Crosses and Crosses

    20131005 - 幽默大师职业赛

    A:POJ 3208 Apocalypse Someday

    B:POJ 3015 Expected Difference

    C:POJ 3016 K-Monotonic

    20131006 - 幽默大师卫冕战

    A:SGU 409 Berland Flag

    B:SGU 361 National Flag

    C:SGU 379  Elevator
    20131007 - 胜利大逃亡

    A:SGU 527 Explode 'Em All

    题意:在一个25*25的地图中放置炸弹,消灭所有的山。一个炸弹可以消灭所在行和所在列的所有山。

    方法:搜索。假设我们已经选取了i行要放置炸弹,那么还有j行的山要消灭,那么这些山只能靠这i行的炸弹来消灭,如果剩下的炸弹所用的列小于等于i,那么答案就是i。根据这点深搜。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 const int N = 30;
     5 
     6 char s[N];
     7 int r, c;
     8 
     9 int sta[N], ans;
    10 
    11 void dfs(int idx, int sx, int cntx, int sy, int cnty) {
    12     if (std::max(cntx, cnty) >= ans) return ;
    13     if (idx == r) {
    14         ans = std::min(ans, std::max(cntx, cnty));
    15     } else {
    16         if (sta[idx] > 0) {
    17             int to = sy | sta[idx];
    18             if (to == sy)
    19                 dfs(idx + 1, sx, cntx, sy, cnty);
    20             else {
    21                 int cc = 0;
    22                 for (int i = 0; i < c; ++i)
    23                     if (to >> i & 1)
    24                         ++cc;
    25                 dfs(idx + 1, sx, cntx, to, cc);
    26             }
    27             dfs(idx + 1, sx | (1 << idx), cntx + 1, sy, cnty);
    28         } else {
    29             dfs(idx + 1, sx, cntx, sy, cnty);
    30         }
    31     }
    32 }
    33 void work() {
    34     memset(sta, 0sizeof sta);
    35 
    36     for (int i = 0; i < r; ++i) {
    37         scanf("%s", s);
    38         for (int j = 0; j < c; ++j)
    39             if (s[j] == '*')
    40                 sta[i] |= 1 << j;
    41     }
    42 
    43     ans = std::max(r, c);
    44     dfs(00000);
    45 
    46     printf("%d ", ans);
    47 }
    48 int main() {
    49     while (2 == scanf("%d%d", &r, &c)) {
    50         work();
    51     }
    52     return 0;
    53 }
    View Code 

    B:CodeForces 37C Old Berland Language

    C:CodeForces 40E Number Table

    20131008 - 想不出名字了呜

    A:HDU 3434 Sequence Adjustment

    B:HDU 4275 Color the Tree

    C:HDU 4270 Dynamic Lover

    2013 ACM亚洲赛网络赛系列 

    B:An Easy Problem for Elfness

    E:Round Table

    F:G(x)

    H:Little Wish~ lyrical step~

    杭州赛区:

    D:Save Labman No.004

    E:Pinball Game 3D

    G:Starloop System

    J: Mex

    题解链接:http://www.cnblogs.com/hewifi/p/3329168.html

    长春赛区:

    A:Poker Shuffle

    B:Good Firewall

    H:Network

    I:Bell

    J: Flyer

    二分不幸运的人所在的位置,由于不幸运的人只有一个,所以如果有人不幸运,那么任何从起点开始,终点>=此人位置的区间中,被发放的海报的总数一定是奇数,否则就一定是偶数,由此满足单调性。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <vector>
     5 typedef __int64 ll;
     6 const ll INF = 1ll << 32;
     7 const int N = 20000 + 10;
     8 
     9 ll a[N], b[N], c[N];
    10 int n;
    11 
    12 bool judge(ll x) {
    13     ll tot = 0;
    14     for (int i = 0; i < n; ++i) {
    15         if (x < a[i]) continue;
    16         if (x >= b[i]) {
    17             tot = tot + 1 + (b[i] - a[i]) / c[i];
    18         } else {
    19             tot = tot + 1 + (x - a[i]) / c[i];
    20         }
    21         tot = tot & 1;
    22     }
    23     return tot & 1;
    24 }
    25 void work() {
    26     for (int i = 0; i < n; ++i)
    27         scanf("%I64d%I64d%I64d", &a[i], &b[i], &c[i]);
    28     ll l = 0, r = INF, mid;
    29     while (r - l > 1) {
    30         mid = (l + r) / 2;
    31         if (judge(mid))
    32             r = mid;
    33         else
    34             l = mid;
    35     }
    36 
    37     if (judge(r)) {
    38         int cnt = 0;
    39         for (int i = 0; i < n; ++i) {
    40             if (r < a[i] || r > b[i]) continue;
    41             if ((r - a[i]) % c[i] == 0)
    42                 ++cnt;
    43         }
    44         printf("%I64d %d ", r, cnt);
    45     } else
    46         puts("DC Qiang is unhappy.");
    47 }
    48 int main() {
    49     while (1 == scanf("%d", &n)) {
    50         work();
    51     }
    52     return 0;
    53 }
    View Code  
    6th BUPT Programming Contest Final

    A:UESTC 1697 Palindrome Again

    这一题本质上是求两个串有多少对公共回文子串,只考虑子串的起始位置和长度的不同。

    E:UESTC 1701 PAC-Phone

    给你两个点集问是否相似。

    H:UESTC 1704 Running

    I: UESTC 1705 The Longest Sequence of Rectangles

    题意:n个矩形的lis,需要严格满足第i个矩形的左下角坐标严格大于第i-1个矩形的右上角坐标。

    思路:树状数组线段树。首先将所有点先按照x轴坐标从小到大排序,如果x轴坐标一样,那么终点总是在起点后面,如果是同一性质的点,为了严格递增,按照y轴坐标从大到小排序(如果是不严格则从小到大)。然后用树状数组或者线段树维护。如果遇到的是起点,则更新数组中的值,如果是终点,则将此点插入数据结构中。

     1 #include <cstring>
     2 #include <cstdio>
     3 #include <algorithm>
     4 struct node {
     5     int x, y, typ, id;
     6 };
     7 
     8 #define lson l, mid, rt << 1
     9 #define rson mid + 1, r, rt << 1 | 1
    10 const int N = 200000 + 5;
    11 
    12 int val[N];
    13 
    14 node p[N];
    15 int y[N], idy;
    16 
    17 int len[N];
    18 int query(int R) {
    19     int re = 0;
    20     for (; R > 0; R -= R & -R) {
    21         re = std::max(re, val[R]);
    22     }
    23     return re;
    24 }
    25 void update(int pos, int v) {
    26     for (; pos <= idy; pos += pos & -pos)
    27         val[pos] = std::max(val[pos], v);
    28 }
    29 bool cmp(const node& a, const node& b) {
    30     if (a.x ^ b.x) return a.x < b.x;
    31     else {
    32         if (a.typ ^ b.typ) return a.typ < b.typ;
    33         else return a.y > b.y;
    34     }
    35 }
    36 void work() {
    37     int n;
    38     scanf("%d", &n);
    39 
    40     idy = 0;
    41     for (int i = 0; i < n; ++i) {
    42         scanf("%d%d", &p[i << 1].x, &p[i << 1].y);
    43         p[i << 1].typ = 0;
    44 
    45         scanf("%d%d", &p[i << 1 | 1].x, &p[i << 1 | 1].y);
    46         p[i << 1 | 1].typ = 1;
    47 
    48         p[i << 1 | 1].id = p[i << 1].id = i;
    49 
    50         y[idy ++] = p[i << 1].y;
    51         y[idy ++] = p[i << 1 | 1].y;
    52     }
    53     std::sort(y, y + idy);
    54     idy = std::unique(y, y + idy) - y;
    55 
    56     n <<= 1;
    57     for (int i = 0; i < n; ++i) {
    58         p[i].y = std::lower_bound(y, y + idy, p[i].y) - y + 1;
    59     }
    60 
    61     memset(val, 0sizeof(int) * (idy + 2));
    62 
    63     int mx, ans = 1;
    64 
    65     std::sort(p, p + n, cmp);
    66     memset(len, 0sizeof len);
    67     for (int i = 0; i < n; ++i) {
    68         if (0 == p[i].typ) {
    69             len[p[i].id] = std::max(len[p[i].id], 1 + query(p[i].y - 1));
    70             ans = std::max(ans, len[p[i].id]);
    71         } else {
    72             update(p[i].y, len[p[i].id]);
    73         }
    74     }
    75     printf("%d ", ans);
    76 }
    77 int main() {
    78     int cas;
    79     scanf("%d", &cas);
    80     while (cas -- > 0) {
    81         work();
    82     }
    83     return 0;
    84 }
    View Code 

     

    ICPC Latin American Regional 2011 - South America/South 

    C:UVALive 5791 Candy's Candy

    题意: 

    有f种口味的糖果,现在要把每颗糖果分到一些packs里面去。packs分两种:

    flavored pack:只有一种口味。

    variety pack:每种口味都有。

    求满足下列要求的分法有多少种:

    1、每个pack至少有两颗糖果。

    2、所有pack的糖果数相同。

    3、variety pack 里每种口味的糖果数量相同。

    4、至少一个variety pack。

    5、每种口味至少一个flavored pack。

    D:UVALive 5792 Diccionário Portuñol

    题意:给你两种串,一种可以当前缀,一种可以当后缀,问两种串合起来,一共有多少种组合。并且没有重合。

    F:UVALive 5794 File Retrieval 

    题意:给你n个串,现在有一个搜索系统,对于任意一个串s,它能够返回所有包含s这个子串的串的集合。

    询问一共有多少种可能的返回集合。对于所有的串s。规模:60个串,每个串长度10^4。

  • 相关阅读:
    Web API 依赖注入与扩展
    ASP.NET Web API 简介
    经典SQL语句大全_主外键_约束
    自学MVC看这里——全网最全ASP.NET MVC 教程汇总
    正则表达式的汉字匹配
    Sql Server 删除所有表
    细说ASP.NET Forms身份认证
    NET Web的身份认证
    C#百万数据查询超时问题
    nodejs 命令行交互
  • 原文地址:https://www.cnblogs.com/hewifi/p/3342772.html
Copyright © 2020-2023  润新知