zoukankan      html  css  js  c++  java
  • 其他-学长杂题讲义

    1. Rasheda And The Zeriba

    大致题意: 给出n条边,判断能否构成一个n边凸多边形,并求出能覆盖该图形的圆的最小半径 1 ≤ n ≤ 1000 。

    http://codeforces.com/gym/100283/problem/A 

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 int N;
     8 double R[1005];
     9 const double _pi = asin(1)*2;
    10 
    11 bool Check(double v)
    12 {
    13     double tmp = 0; int i;
    14     for (i = 1; i <= N; ++i)
    15         if ((tmp += asin(R[i]/2/v)*2) > 2*_pi) break;
    16     return i == N+1;
    17 }
    18 
    19 int main()
    20 {
    21     freopen("zeriba.in", "r", stdin);
    22     int T;
    23     scanf("%d", &T);
    24     for (int ca = 1; ca <= T; ++ca) {
    25         scanf("%d", &N);
    26         double sum = 0, mx = 0; int i;
    27         for (i = 1; i <= N; ++i)
    28             scanf("%lf", &R[i]), sum += R[i], mx = max(mx, R[i]);
    29         for (i = 1; i <= N; ++i)
    30             if (sum-R[i] <= R[i]) break;
    31         if (i != N+1) { printf("Case %d: can't form a convex polygon
    ", ca); continue; }
    32         double l = mx/2, r = sum/4;
    33         while (fabs(l-r) >= 0.000001) {
    34             double mid = (l+r)/2;
    35             if (Check(mid)) r = mid;
    36             else l = mid;
    37         }
    38         printf("Case %d: %.4lf
    ", ca, l);
    39     }
    40     return 0;
    41 }
    View Code

     2. Fitting boxes

    大致题意:给出两个矩形长宽(1 <= x, y, a, b <= 1000),判断能否使其中一个完全覆盖另一个。

    http://codeforces.com/gym/100738/problem/A

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <algorithm>
     4 
     5 const double _PI = asin(1)*2;
     6 
     7 using namespace std;
     8 
     9 inline double P(double v) { return v * v; }
    10 
    11 bool Test(double x, double y, double a, double b)
    12 {
    13     if (x*y < a*b || a > x) return false;
    14     if (b <= y) return true;
    15     if (P(y*b) < P(a*a)+P(a*b)-P(a*y)) return false;
    16     
    17     double tmp = _PI/2 - (atan(sqrt(P(y)/(P(a)+P(b)-P(y)))) - atan(a/b));
    18     double tmp2 = b*sin(tmp)+a*cos(tmp);
    19     return 0 <= tmp2 && tmp2 <= x;
    20 }
    21 
    22 int main()
    23 {
    24     double t1, t2, t3, t4;
    25     int ans = 0;
    26     scanf("%lf%lf%lf%lf", &t1, &t2, &t3, &t4);
    27 
    28     ans |= Test(t1, t2, t3, t4);
    29     ans |= Test(t1, t2, t4, t3);
    30     ans |= Test(t2, t1, t3, t4);
    31     ans |= Test(t2, t1, t4, t3);
    32     
    33     swap(t1, t3), swap(t2, t4);
    34     
    35     ans |= Test(t1, t2, t3, t4);
    36     ans |= Test(t1, t2, t4, t3);
    37     ans |= Test(t2, t1, t3, t4);
    38     ans |= Test(t2, t1, t4, t3);
    39     
    40     if (ans) printf("Yes
    ");
    41     else printf("No
    ");
    42     return 0;
    43 }
    View Code

    3. Pretty Buses

    大致题意:一个n个点m条边的无向图,每条边有一个权值。初始时,点i处有巴士i和司机i,你可以有两种操作:(1)Drive b x y,把巴士b从x点开到y点并付出这条边的权值的费用;(2)Move d x y,司机d从巴士x移动的巴士y上,没有花费 所有司机要集中在一个点,并且每个司机的换乘次数不多于25 求最小花费,并给出一种合理的方案 1 ≤ n ≤ 200000, 1 ≤ m ≤ 400000

    http://codeforces.com/gym/100738/problem/E

    #include <cstdio>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    const int _N = 400005;
    
    struct tmpeg {
        int x, y, w;
        tmpeg(int x, int y, int w):
            x(x), y(y), w(w) { }
        bool operator < (const tmpeg t) const
        {
            return w > t.w;
        }
    };
    
    priority_queue<tmpeg> Q;
    vector<int> G[_N], dri[_N];
    int veh[_N], siz[_N], Dad[_N];
    
    inline void Ins(int x, int y) { G[x].push_back(y); return; }
    
    void diudiu(int node, int dad)
    {
        int mx = node;
        for (int i = G[node].size()-1; i >= 0; --i) {
            int v = G[node][i];
            if (v == dad) continue;
            diudiu(v, node);
            printf("Drive %d %d %d
    ", veh[v], v, node);
            int a = veh[node], b = veh[v];
            if (siz[a] < siz[b]) swap(a, b);
            veh[node] = veh[v] = a;
            siz[a] += siz[b];
            for (int j = dri[b].size()-1; j >= 0; --j) {
                printf("Move %d %d %d
    ", dri[b][j], b, a);
                dri[a].push_back(dri[b][j]), veh[dri[b][j]] = a;
            }
            
        }
        return;
    }
    
    int GetDad(int v) { return Dad[v] == v ? v : Dad[v] = GetDad(Dad[v]); }
    
    int main()
    {
        int N, M, i;
        scanf("%d%d", &N, &M);
        for (i = 1; i <= M; ++i) {
            int x, y, w;
            scanf("%d%d%d", &x, &y, &w);
            Q.push(tmpeg(x, y, w));
        }
        long long ans = 0; int cnt = 0;
        for (i = 1; i <= N; ++i)
            Dad[i] = i, siz[i] = 1, veh[i] = i, dri[i].push_back(i);
        while (true) {
            tmpeg tmp = Q.top(); Q.pop();
            int tx = GetDad(tmp.x), ty = GetDad(tmp.y);
            if (tx != ty) {
                Dad[tx] = ty, Ins(tmp.x, tmp.y), Ins(tmp.y, tmp.x);
                ++cnt, ans += tmp.w;
                if (cnt == N-1) break;
            }
        }
        printf("%I64d
    ", ans);
        
        diudiu(1, 0);
        printf("Done
    ");
        return 0;
    }
    View Code

    4. Mishka and Interesting sum

    大致题意:询问数列 A 中 [L, R] 区间出现次数为偶数次的数字,每个数只算一次的异或和。比如对于 {1, 3, 3, 3, 4, 4} ,答案是 1^3^4 。

    http://codeforces.com/contest/703/problem/D

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int _N = 1050000;
     7 
     8 struct query {
     9     int l, r, id;
    10     bool operator < (const query tmp) const
    11     {
    12         return this->l < tmp.l;
    13     }
    14 } Q[_N];
    15 
    16 int pos, N, M, N_A;
    17 int A[_N], B[_N], C[_N], sum[_N], fst[_N], nxt[_N], ans[_N];
    18 bool mk[_N];
    19 
    20 void Add(int k, int d)
    21 {
    22     for (int i = k; i <= N; i += i & -i)
    23         C[i] ^= d;
    24     return;
    25 }
    26 
    27 int GetSum(int k)
    28 {
    29     int tmp = 0;
    30     for (int i = k; i; i ^= i & -i)
    31         tmp ^= C[i];
    32     return tmp;
    33 }
    34 
    35 int hs(int v) { return lower_bound(A+1, A+1+N_A, v)-A; }
    36 
    37 int main()
    38 {
    39     int i;
    40     scanf("%d", &N);
    41     for (i = 1; i <= N; ++i)
    42         scanf("%d", &A[i]), sum[i] = sum[i-1]^A[i], B[i] = A[i];
    43     scanf("%d", &M);
    44     for (i = 1; i <= M; ++i)
    45         scanf("%d%d", &Q[i].l, &Q[i].r), Q[i].id = i;
    46     
    47     sort(Q+1, Q+1+M);
    48     sort(A+1, A+1+N);
    49     N_A = unique(A+1, A+1+N)-A-1;
    50     for (i = 1; i <= N; ++i) {
    51         int tmp;
    52         if (!mk[tmp = hs(B[i])])
    53             mk[tmp] = true, Add(i, B[i]);
    54     }
    55     pos = 1;
    56     for (i = N; i >= 1; --i) {
    57         int tmp = hs(B[i]);
    58         nxt[i] = fst[tmp], fst[tmp] = i;
    59     }
    60     
    61     for (i = 1; i <= M; ++i) {
    62         while (pos < Q[i].l) {
    63             Add(pos, B[pos]);
    64             if (nxt[pos]) Add(nxt[pos], B[pos]);
    65             ++pos;
    66         }
    67         ans[Q[i].id] = GetSum(Q[i].r)^sum[Q[i].r]^sum[Q[i].l-1];
    68     }
    69     for (i = 1; i <= M; ++i)
    70         printf("%d
    ", ans[i]);
    71     return 0;
    72 }
    View Code

    5. Queries

    大致题意:维护一个序列,支持 1.单点修改 2.查询某区间 [l, r] 中所有合理的 [i, j] (l <= i <= j <= r) 的异或结果的和。用 Elf(i, j) 表示 [i, j] 中所有数的异或结果,则 [l, r] 查询的结果应为 ∑Elf(i, j)  ( [i, j] ⊆ [l, r] ) 。

    http://codeforces.com/gym/100739/problem/A

    一定注意,尽管根据定义 lsum0(表示左起前缀和中 0 的个数) = 区间长度 - lsum1 (表示左起前缀和中 1 的个数),但是最好在线段树中同时维护这两个变量,这样在查询操作时可以避免一些特判。理论上只记一个变量+特判是可以的,我最初也是这么写的,也就 Wa 了那么七八次吧,还要感谢 newuser 大佬指出我特判的愚蠢性……OrzOrzOrz

     1 #include <cstdio>
     2 
     3 const int MOD = 4001;
     4 const int _N = 2800000;
     5 
     6 int Tot, N, M;
     7 int lsum0[_N], lsum[_N], rsum0[_N], rsum[_N], xos[_N], cnt[_N], lson[_N], rson[_N], root[11];
     8 
     9 void Modify(int &p, int l, int r, int k, int v)
    10 {
    11     if (!p) p = ++Tot;
    12     if (l == r) { lsum[p] = rsum[p] = cnt[p] = xos[p] = v, lsum0[p] = rsum0[p] = v^1; return; }
    13     int mid = l+r >> 1;
    14     if (!lson[p]) lson[p] = ++Tot;
    15     if (!rson[p]) rson[p] = ++Tot;
    16     if (k <= mid) Modify(lson[p], l, mid, k, v);
    17     else Modify(rson[p], mid+1, r, k, v);
    18     lsum[p] = (lsum[lson[p]] + (xos[lson[p]] ? lsum0[rson[p]] : lsum[rson[p]]))%MOD;
    19     rsum[p] = (rsum[rson[p]] + (xos[rson[p]] ? rsum0[lson[p]] : rsum[lson[p]]))%MOD;
    20     lsum0[p] = (lsum0[lson[p]] + (xos[lson[p]] ? lsum[rson[p]] : lsum0[rson[p]]))%MOD;
    21     rsum0[p] = (rsum0[rson[p]] + (xos[rson[p]] ? rsum[lson[p]] : rsum0[lson[p]]))%MOD;
    22     xos[p] = xos[lson[p]] ^ xos[rson[p]];
    23     cnt[p] = (cnt[lson[p]]+cnt[rson[p]])%MOD;
    24     cnt[p] = (cnt[p]+rsum[lson[p]]*lsum0[rson[p]]%MOD)%MOD;
    25     cnt[p] = (cnt[p]+rsum0[lson[p]]*lsum[rson[p]]%MOD)%MOD;
    26     return;
    27 }
    28 
    29 int Query(int &p, int l, int r, int s, int t, int &tmp_l, int &tmp_r, int &tmp_x, int &tmp_l0, int &tmp_r0)
    30 {
    31     if (!p) p = ++Tot;
    32     if (s <= l && r <= t) { tmp_l = lsum[p], tmp_r = rsum[p], tmp_x = xos[p], tmp_l0 = lsum0[p], tmp_r0 = rsum0[p]; return cnt[p]; }
    33     int mid = l+r >> 1, l_l=0, l_r=0, l_x=0, r_l=0, r_r=0, r_x=0, l_cnt=0, r_cnt=0, l_l0=0, l_r0=0, r_l0=0, r_r0=0;
    34     if (t >= l && s <= mid) l_cnt = Query(lson[p], l, mid, s, t, l_l, l_r, l_x, l_l0, l_r0);
    35     if (t > mid && s <= r) r_cnt = Query(rson[p], mid+1, r, s, t, r_l, r_r, r_x, r_l0, r_r0);
    36     
    37     tmp_l = (l_l + (l_x ? r_l0 : r_l))%MOD;
    38     tmp_r = (r_r + (r_x ? l_r0 : l_r))%MOD;
    39     tmp_l0 = (l_l0 + (l_x ? r_l : r_l0))%MOD;
    40     tmp_r0 = (r_r0 + (r_x ? l_r : l_r0))%MOD;
    41     tmp_x = l_x ^ r_x;
    42     int tmp_cnt = (l_cnt+r_cnt)%MOD;
    43     tmp_cnt = (tmp_cnt+l_r*r_l0%MOD)%MOD;
    44     tmp_cnt = (tmp_cnt+l_r0*r_l%MOD)%MOD;
    45     return tmp_cnt;
    46 }
    47 
    48 int main()
    49 {
    50     int i, j;
    51     scanf("%d%d", &N, &M);
    52     for (i = 1; i <= N; ++i) {
    53         int tmp;
    54         scanf("%d", &tmp);
    55         for (j = 0; j < 11; ++j)
    56             Modify(root[j], 1, N, i, (tmp>>j)&1);
    57     }
    58     while (M--) {
    59         int ins, x, y;
    60         scanf("%d%d%d", &ins, &x, &y);
    61         if (ins == 1) {//change
    62             for (j = 0; j < 11; ++j)
    63                 Modify(root[j], 1, N, x, (y>>j)&1);
    64         } else {//query
    65             int ans = 0;
    66             int tl, tr, tx, tl0, tr0;
    67             for (j = 0; j < 11; ++j)
    68                 ans = (ans+(Query(root[j], 1, N, x, y, tl, tr, tx, tl0, tr0)<<j)%MOD)%MOD;
    69             printf("%d
    ", (ans+MOD)%MOD);
    70         }
    71     }
    72     return 0;
    73 }
    View Code

    6. Decomposition into Good Strings

    大致题意:定义 good string 为正好包含 k 种不同字母的字符串(如当 k = 2 时,abbbba 是一个 good string)。给定 k 和一个长为 n (1 <= n <= 200000)的字符串,求该字符串的每个前缀最少可以被分割为多少个 good string 。即输出 n 个数,分别对应原字符串的 n 个前缀的答案。

    http://codeforces.com/gym/100971/problem/M

     1 #include <cstdio>
     2 
     3 char A[250000];
     4 int f[250000], mk[300], cnt, K, pos;
     5 
     6 void Update(int i)
     7 {
     8     if (++mk[A[i]] == 1) ++cnt;
     9     if (cnt < K) { f[i] = -1; return; }
    10     while (cnt > K) {
    11         if (!--mk[A[pos]]) --cnt;
    12         ++pos;
    13     }
    14     if (pos == -1) pos = 1;
    15     bool flag = false;
    16     while (f[pos-1] == -1) {
    17         if (mk[A[pos]] == 1) { flag = true; break; }
    18         --mk[A[pos]], ++pos;
    19     }
    20     if (flag) { f[i] = -1; return; }
    21     f[i] = f[pos-1]+1;
    22     return;
    23 }
    24 
    25 int main()
    26 {
    27     char tt;
    28     int i;
    29     scanf("%d", &K);
    30     f[0] = 0, pos = -1;
    31     while ((tt = getchar()) < 'a' || tt > 'z');
    32         A[i = 1] = tt, Update(i);
    33     while ((tt = getchar()) >= 'a' && tt <= 'z')
    34         A[++i] = tt, Update(i);
    35     for (int t = 1; t <= i; ++t)
    36         printf("%d ", f[t]);
    37     return 0;
    38 }
    View Code
  • 相关阅读:
    VMware安装Centos7超详细过程
    Linux部署Web项目
    Entity Framework快速入门IQueryable与IEnumberable的区别
    ASP.NET MVC3中的路由系统(Routes)
    C# Lambda表达式概述
    WCF大数据量传输解决要点
    div滚动条样式设计
    ASP.NET MVC 自定义路由
    C# Lambda表达式学习笔记
    C# 操作excel
  • 原文地址:https://www.cnblogs.com/ghcred/p/9278393.html
Copyright © 2011-2022 走看看