zoukankan      html  css  js  c++  java
  • Multi-University Training Contest 4

    (hdoj 4897-4906)

    1001

       LCT和树链剖分都可以做,简单起见就说说树链剖分,LCT类似。 

       首先注意到一条路径上是logn条重链和logn条轻边。

       当我们给一个点的所有边上的邻居边打标记时,如果该点在重链上,会影响他的轻孩子们。(要特殊考虑链头和链尾之类的)。

       那么我们可以给重链上的点打标记,表示这个点的轻孩子们被翻转了没。

       那么一个轻边就可以直接询问出来。复杂度:O(nlog2n)。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <vector>
      7 using namespace std;
      8 
      9 const int MAX_N = int(1e5) + 10;
     10 int n;
     11 
     12 vector<int> E[MAX_N];
     13 int que[MAX_N], qh, qt, fa[MAX_N], size[MAX_N];
     14 int pathIdx[MAX_N], pathFirst[MAX_N], dep[MAX_N];
     15 
     16 struct Tree {
     17     int l, r;
     18     bool rev;
     19     int sum;
     20 
     21     Tree*pl, *pr;
     22 
     23     void applyRev() {
     24         rev ^= 1;
     25         sum = r - l - sum;
     26     }
     27 
     28     void relax() {
     29         if (rev) {
     30             pl->applyRev(), pr->applyRev();
     31             rev = false;
     32         }
     33     }
     34 
     35     void update() {
     36         sum = pl->sum + pr->sum;
     37     }
     38 
     39     Tree(int l, int r) :
     40         l(l), r(r), rev(false) {
     41         sum = 0;
     42         if (l + 1 == r) {
     43             pl = pr = 0;
     44             return;
     45         }
     46         pl = new Tree(l, l + r >> 1), pr = new Tree(l + r >> 1, r);
     47     }
     48 
     49     int querySum(int L, int R) {
     50         if (L >= R)
     51             return 0;
     52         if (L <= l && R >= r)
     53             return sum;
     54         if (L >= r || l >= R)
     55             return 0;
     56         relax();
     57         return pl->querySum(L, R) + pr->querySum(L, R);
     58     }
     59 
     60     void reverse(int L, int R) {
     61         if (L >= R)
     62             return;
     63         if (L <= l && R >= r) {
     64             applyRev();
     65             return;
     66         }
     67         if (L >= r || l >= R)
     68             return;
     69         relax();
     70         pl->reverse(L, R), pr->reverse(L, R);
     71         update();
     72     }
     73 };
     74 
     75 Tree*sumTree[MAX_N], *markTree[MAX_N];
     76 
     77 void build(int vs) { //build path-composition
     78     qh = qt = 0;
     79     que[qt++] = vs, fa[vs] = -1, dep[vs] = 0;
     80     while (qh < qt) {
     81         int u = que[qh++];
     82         vector<int>::iterator v;
     83         for(v=E[u].begin(); v!=E[u].end(); v++)
     84             if (*v != fa[u]) {
     85                 fa[*v] = u, que[qt++] = *v, dep[*v] = dep[u] + 1;
     86             }
     87     }
     88     for (int i = n - 1; i >= 0; --i) {
     89         int u = que[i];
     90         size[u] = 1;
     91         vector<int>::iterator v;
     92         for(v=E[u].begin(); v!=E[u].end(); v++)
     93             if (fa[*v] == u)
     94                 size[u] += size[*v];
     95     }
     96 
     97     memset(pathFirst, -1, sizeof pathFirst);
     98     for (int i = 0; i < n; ++i) {
     99         int u = que[i];
    100         if (pathFirst[u] != -1)
    101             continue;
    102         int top = u, cnt = 0;
    103         for (;;) {
    104             pathFirst[u] = top;
    105             pathIdx[u] = cnt++;
    106 
    107             int nxt = -1;
    108             vector<int>::iterator v;
    109             for(v=E[u].begin(); v!=E[u].end(); v++)
    110                 if (fa[*v] == u)
    111                     if (nxt == -1 || size[*v] > size[nxt]) {
    112                         nxt = *v;
    113                     }
    114             if (nxt == -1)
    115                 break;
    116             u = nxt;
    117         }
    118         sumTree[top] = new Tree(0, cnt);
    119         markTree[top] = new Tree(0, cnt);
    120     }
    121 }
    122 
    123 int col[MAX_N]; //for light edge u and u's father
    124 
    125 int getLightEdge(int u) {
    126     //u and fa[u] is a light edge, get its weight
    127     int v = fa[u];
    128     return col[u] ^ markTree[pathFirst[v]]->querySum(pathIdx[v], pathIdx[v] + 1);
    129 }
    130 
    131 int query(int x, int y) {
    132     int ret = 0;
    133     for (;;) {
    134         if (pathFirst[x] == pathFirst[y]) {
    135             int l = pathIdx[x], r = pathIdx[y];
    136             if (l > r)
    137                 swap(l, r);
    138             ret += sumTree[pathFirst[x]]->querySum(l + 1, r + 1);
    139             break;
    140         }
    141         if (dep[pathFirst[x]] < dep[pathFirst[y]])
    142             swap(x, y);
    143         //x goest first
    144         ret += sumTree[pathFirst[x]]->querySum(1, pathIdx[x] + 1);
    145         x = pathFirst[x];
    146         ret += getLightEdge(x);
    147         x = fa[x];
    148     }
    149     return ret;
    150 }
    151 
    152 void reversePath(int x, int y) {
    153     for (;;) {
    154         if (pathFirst[x] == pathFirst[y]) {
    155             int l = pathIdx[x], r = pathIdx[y];
    156             if (l > r)
    157                 swap(l, r);
    158             sumTree[pathFirst[x]]->reverse(l + 1, r + 1);
    159             break;
    160         }
    161         if (dep[pathFirst[x]] < dep[pathFirst[y]])
    162             swap(x, y);
    163         //x goest first
    164         sumTree[pathFirst[x]]->reverse(1, pathIdx[x] + 1);
    165         x = pathFirst[x];
    166         col[x] ^= 1;
    167         x = fa[x];
    168     }
    169 }
    170 
    171 void reverseAdj(int x, int y) {
    172     for (;;) {
    173         if (pathFirst[x] == pathFirst[y]) {
    174             int l = pathIdx[x], r = pathIdx[y];
    175             if (l > r)
    176                 swap(l, r), swap(x, y);
    177             markTree[pathFirst[x]]->reverse(l, r + 1);
    178             if (pathFirst[x] == x)
    179                 col[x] ^= 1;
    180             else
    181                 sumTree[pathFirst[x]]->reverse(l, l + 1);
    182 
    183             sumTree[pathFirst[y]]->reverse(r + 1, r + 2);
    184             break;
    185         }
    186         if (dep[pathFirst[x]] < dep[pathFirst[y]])
    187             swap(x, y);
    188         //x goest first
    189         markTree[pathFirst[x]]->reverse(0, pathIdx[x] + 1);
    190         sumTree[pathFirst[x]]->reverse(pathIdx[x] + 1, pathIdx[x] + 2);
    191         x = pathFirst[x];
    192         col[x] ^= 1;
    193         x = fa[x];
    194     }
    195 }
    196 
    197 int main() {
    198     int T;
    199     scanf("%d",&T);
    200     while (T--) {
    201         scanf("%d",&n);
    202         for (int i = 0; i < n; ++i) {
    203             E[i].clear();
    204         }
    205         memset(col, 0, sizeof col);
    206         for (int i = 0; i < n - 1; ++i) {
    207             int a, b;
    208             scanf("%d %d",&a,&b);
    209             --a, --b;
    210             E[a].push_back(b), E[b].push_back(a);
    211         }
    212 
    213         build(0);
    214 
    215         int Q;
    216         scanf("%d",&Q);
    217         while (Q--) {
    218             int t, a, b;
    219             scanf("%d%d%d", &t, &a, &b), --a, --b;
    220             if (t == 1) {
    221                 reversePath(a, b);
    222             } else if (t == 2) {
    223                 reverseAdj(a, b);
    224             } else {
    225                 printf("%d
    ", query(a, b));
    226             }
    227         }
    228     }
    229 }

    1002

       首先二分答案,并且注意到一个点开始的子串越长字典序越大。

       那么现在问题变成了给你一个环,每个点i能往后延伸长度ri,问存不存在一个 从某点跳k次绕一圈跳回自己的路径。

       首先递归删掉ri = 0的点,因为这些点不能经过。那么现在所有点的r都>0,那么如果还有n个点,那么最多跳n次。注意到可行次数显然是一个区间,那么只要求出最小跳的次数就行了。

       最小跳的次数就是枚举一个开始点然后不停往后狂跳。

       ADD

       n ≤ 10w的话怎么做?

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <vector>
      7 using namespace std;
      8 const int MAX_N = 4000 + 10;
      9 char S[MAX_N];
     10 int n, k;
     11 int lcp[MAX_N][MAX_N];
     12 
     13 struct Sub {
     14     int l, r; //[l,r)
     15 
     16     Sub(int l, int r) :
     17         l(l), r(r) {
     18     }
     19 
     20     int size() {
     21         return r - l;
     22     }
     23     char charAt(int x) {
     24         if (x < size())
     25             return S[l + x];
     26         else
     27             return 0;
     28     }
     29 };
     30 
     31 int Lcp(Sub a, Sub b) {
     32     return min(lcp[a.l][b.l], min((int) a.size(), (int) b.size()));
     33 }
     34 
     35 bool operator<(Sub a, Sub b) {
     36     int L = Lcp(a, b);
     37     return a.charAt(L) < b.charAt(L);
     38 }
     39 
     40 int step[MAX_N];
     41 
     42 bool check(Sub M) {
     43     vector<int> nxt(n);
     44     for (int i = 0; i < n; ++i) {
     45         int L = Lcp(Sub(i, i + n), M);
     46         if (S[(i + L) % n] < M.charAt(L))
     47             nxt[i] = n;
     48         else
     49             nxt[i] = L;
     50     }
     51 
     52 //    for (int i = 0; i < n; ++i) {
     53 //        cout << nxt[i] << " ";
     54 //    }
     55 //    cout << endl;
     56     //clean
     57     for (;;) {
     58         bool done = true;
     59         for (int i = 0; i < nxt.size(); ++i) {
     60             if (nxt[i] == 0) {
     61                 for (int j = 0; j < nxt.size(); ++j)
     62                     if (j != i) {
     63                         if (j < i && j + nxt[j] >= i)
     64                             --nxt[j];
     65                         else if (j > i && j + nxt[j] >= i + nxt.size())
     66                             --nxt[j];
     67                     }
     68                 nxt.erase(nxt.begin() + i);
     69                 done = false;
     70                 break;
     71             }
     72         }
     73         if (done)
     74             break;
     75     }
     76 
     77 //    for (int i = 0; i < nxt.size(); ++i) {
     78 //        cout << nxt[i] << " ";
     79 //    }
     80 //    cout << endl;
     81 
     82     if (k > nxt.size())
     83         return false;
     84 
     85     for (int i = 0; i < nxt.size() * 2; ++i) {
     86         step[i] = i + nxt[i % nxt.size()];
     87     }
     88 
     89     for (int i = 0; i < nxt.size(); ++i) {
     90         int need = 0, at = i;
     91         while (at < i + nxt.size()) {
     92             at = step[at];
     93             ++need;
     94         }
     95         if (need <= k)
     96             return true;
     97     }
     98 
     99     return false;
    100 }
    101 
    102 int main() {
    103     int T;
    104     scanf("%d",&T);
    105     while (T--) {
    106         scanf("%d %d",&n,&k);
    107 
    108         memset(S, 0, sizeof S);
    109 
    110         scanf("%s", S);
    111 
    112         for (int i = n; i < n + n; ++i) {
    113             S[i] = S[i - n];
    114         }
    115 
    116         for (int i = n + n - 1; i >= 0; --i) {
    117             for (int j = n + n - 1; j >= 0; --j) {
    118                 if (S[i] == S[j])
    119                     lcp[i][j] = lcp[i + 1][j + 1] + 1;
    120                 else
    121                     lcp[i][j] = 0;
    122             }
    123         }
    124 
    125         vector<Sub> subs;
    126         for (int i = 0; i < n; ++i) {
    127             for (int j = i; j < i + (i == 0 ? n : n - 1); ++j) {
    128                 subs.push_back(Sub(i, j + 1));
    129             }
    130         }
    131         sort(subs.begin(), subs.end());
    132 
    133         int l = -1, r = subs.size() - 1;
    134         while (l + 1 < r) {
    135             int m = (l + r) >> 1;
    136             if (check(subs[m]))
    137                 r = m;
    138             else
    139                 l = m;
    140         }
    141 
    142         Sub ans = subs[r];
    143         for (int i = 0; i < ans.size(); ++i) {
    144             printf("%c", ans.charAt(i));
    145         }
    146         puts("");
    147 //        check(ans);
    148     }
    149     return 0;
    150 }

    1003

       考虑dpi,j 表示S的前i个和T 的前j个的LCT。 注意到,如果我们枚举了一个长度为i的串,我们关心哪些信息?有意义的只有dpi,∗的值!对于i,我们暴力记录所有dpi,∗的值来。

       注意到dpi,j 和dpi,j−1最多差1,因此状态数量很少。

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <vector>
      7 #include <map>
      8 using namespace std;
      9 const int MOD = int(1e9) + 7;
     10 string S;
     11 int m;
     12 const string ACGT = "ACGT";
     13 
     14 vector<int> getNext(vector<int> cur, char c) {
     15     for (int i = S.size(); i >= 1; --i) {
     16         if (S[i - 1] == c)
     17             cur[i] = max(cur[i - 1] + 1, cur[i]);
     18     }
     19     for (int i = 1; i <= S.size(); ++i) {
     20         cur[i] = max(cur[i], cur[i - 1]);
     21     }
     22     return cur;
     23 }
     24 
     25 map<vector<int>, int> idmp;
     26 vector<vector<int> > states;
     27 
     28 void dfs(vector<int> cur) {
     29     if (idmp.count(cur))
     30         return;
     31 
     32     int me = idmp.size();
     33     idmp[cur] = me;
     34     states.push_back(cur);
     35 
     36     for (int i = 0; i < ACGT.size(); ++i) {
     37         dfs(getNext(cur, ACGT[i]));
     38     }
     39 }
     40 
     41 vector<vector<int> > trans;
     42 
     43 void addIt(int&x, int c) {
     44     x += c;
     45     if (x >= MOD)
     46         x -= MOD;
     47 }
     48 
     49 int calcStates(string S) {
     50     ::S = S;
     51     idmp.clear(), states.clear();
     52     vector<int> init(S.size() + 1, 0);
     53     dfs(init);
     54     return states.size();
     55 }
     56 
     57 int maxState;
     58 string who;
     59 
     60 void dfs(string cur, int rem, int nused) {
     61     if (rem == 0) {
     62         int tmp = calcStates(cur);
     63 //        maxState = max(maxState, calcStates(cur));
     64         if (tmp > maxState) {
     65             maxState = tmp;
     66             who = cur;
     67         }
     68         return;
     69     }
     70     for (int i = 0; i < 4 && i <= nused; ++i) {
     71         dfs(cur + ACGT[i], rem - 1, max(nused, i + 1));
     72     }
     73 }
     74 
     75 int main() {
     76     int T;
     77     cin >> T;
     78     while (T--) {
     79         cin >> S;
     80         cin >> m;
     81 
     82         idmp.clear(), states.clear();
     83 
     84         vector<int> init(S.size() + 1, 0);
     85         dfs(init);
     86         trans.assign(idmp.size(), vector<int>(4, 0));
     87 
     88         for (int i = 0; i < states.size(); ++i) {
     89             for (int j = 0; j < 4; ++j) {
     90                 trans[i][j] = idmp[getNext(states[i], ACGT[j])];
     91             }
     92         }
     93 
     94         vector<int> am(states.size(), 0);
     95         vector<int> nam = am;
     96 
     97         am[idmp[init]] = 1;
     98 
     99         for (int i = 0; i < m; ++i) {
    100             fill(nam.begin(), nam.end(), 0);
    101             for (int a = 0; a < states.size(); ++a) {
    102                 for (int b = 0; b < 4; ++b) {
    103                     addIt(nam[trans[a][b]], am[a]);
    104                 }
    105             }
    106             am = nam;
    107         }
    108 
    109         vector<int> ans(S.size() + 1, 0);
    110         for (int i = 0; i < states.size(); ++i) {
    111             addIt(ans[states[i].back()], am[i]);
    112         }
    113 
    114         for (int i = 0; i <= S.size(); ++i) {
    115             cout << ans[i] << endl;
    116         }
    117     }
    118 }

    1004

       不妨枚举a,b作为直径,然后计算该情况的概率。注意到如果不考虑字典序这其实等价于其它选的点满足Dc→a ≤ Da→b  并且 Dc→b ≤ Da→b。

       考虑字典序也类似。

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <vector>
      7 using namespace std;
      8 
      9 const int MAX_N = 1000 + 10;
     10 int n, k;
     11 int lab[MAX_N];
     12 int dist[MAX_N][MAX_N], ans[MAX_N][MAX_N];
     13 
     14 vector<int> E[MAX_N];
     15 
     16 int cnt[MAX_N];
     17 
     18 void dfs(int u, int p, int d, int w, int dst[], int am[]) {
     19 
     20     if (++cnt[lab[u]] == 1)
     21         ++w;
     22 
     23     dst[u] = d;
     24     am[u] = w;
     25     vector<int>::iterator x;
     26     for(x=E[u].begin(); x!=E[u].end(); x++)
     27         if (*x != p)
     28             dfs(*x, u, d + 1, w, dst, am);
     29 
     30     --cnt[lab[u]];
     31 }
     32 
     33 typedef int T;
     34 struct Index: public vector<T> {
     35     void doit() {
     36         sort(begin(), end());
     37         erase(unique(begin(), end()), end());
     38     }
     39     int get(T x) {
     40         return lower_bound(begin(), end(), x) - begin();
     41     }
     42 };
     43 
     44 double comb[MAX_N][MAX_N];
     45 
     46 int main() {
     47     for (int i = 0; i < MAX_N; ++i) {
     48         for (int j = 0; j <= i; ++j) {
     49             comb[i][j] =
     50                 (i == 0 || j == 0) ?
     51                 1 : (comb[i - 1][j] + comb[i - 1][j - 1]);
     52         }
     53     }
     54 
     55     int T;
     56     cin >> T;
     57     while (T--) {
     58         cin >> n >> k;
     59         for (int i = 0; i < n; ++i) {
     60             E[i].clear();
     61         }
     62         for (int i = 0; i < n - 1; ++i) {
     63             int a, b;
     64             cin >> a >> b, --a, --b;
     65             E[a].push_back(b);
     66             E[b].push_back(a);
     67         }
     68 
     69         Index idx;
     70 
     71         for (int i = 0; i < n; ++i) {
     72             cin >> lab[i];
     73             idx.push_back(lab[i]);
     74         }
     75 
     76         idx.doit();
     77 
     78         for (int i = 0; i < n; ++i) {
     79             lab[i] = idx.get(lab[i]);
     80         }
     81 
     82         memset(cnt, 0, sizeof cnt);
     83 
     84         for (int i = 0; i < n; ++i) {
     85             dfs(i, -1, 0, 0, dist[i], ans[i]);
     86         }
     87 
     88         if (k == 1) {
     89             printf("%0.10lf
    ", 0.);
     90             continue;
     91         }
     92 
     93         double ans = 0;
     94 
     95         for (int a = 0; a < n; ++a) {
     96             for (int b = a + 1; b < n; ++b) {
     97                 int cnt = 0;
     98                 for (int c = 0; c < n; ++c)
     99                     if (a != c && b != c) {
    100                         int L = dist[a][b];
    101                         if (dist[a][c] > L || (dist[a][c] == L && c < b))
    102                             continue;
    103                         if (dist[b][c] > L || (dist[b][c] == L && c < a))
    104                             continue;
    105                         ++cnt;
    106                     }
    107                 double pb = comb[cnt][k - 2] / comb[n][k];
    108                 ans += pb * ::ans[a][b];
    109             }
    110         }
    111 
    112         printf("%0.10lf
    ", ans);
    113     }
    114 }

    1005

       大家肯定会做吧。

     

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <string>
     6 using namespace std;
     7 
     8 const int MAX_N = int(1e3) + 10;
     9 const int MOD = int(1e9) + 7;
    10 int dp1[MAX_N][1024], dp2[MAX_N][1024], n, a[MAX_N];
    11 
    12 void addIt(int&x, int c) {
    13     x += c;
    14     if (x >= MOD)
    15         x -= MOD;
    16 }
    17 
    18 int main() {
    19     int T;
    20     cin >> T;
    21     for (int it = 0; it < T; ++it) {
    22         cin >> n;
    23         for (int i = 0; i < n; ++i) {
    24             cin >> a[i];
    25         }
    26         memset(dp1, 0, sizeof dp1);
    27 
    28         dp1[0][0] = 1;
    29         for (int i = 0; i < n; ++i) {
    30             for (int j = 0; j < 1024; ++j) {
    31                 if (dp1[i][j] > 0) {
    32                     addIt(dp1[i + 1][j], dp1[i][j]);
    33                     addIt(dp1[i + 1][j ^ a[i]], dp1[i][j]);
    34                 }
    35             }
    36         }
    37         memset(dp2, 0, sizeof dp2);
    38 
    39         dp2[n][1023] = 1;
    40         for (int i = n - 1; i >= 0; --i) {
    41             for (int j = 0; j < 1024; ++j) {
    42                 if (dp2[i + 1][j] > 0) {
    43                     addIt(dp2[i][j], dp2[i + 1][j]);
    44                     addIt(dp2[i][j & a[i]], dp2[i + 1][j]);
    45                 }
    46             }
    47         }
    48         int ans = 0;
    49         for (int i = 0; i < n; ++i) {
    50             for (int j = 0; j < 1024; ++j) {
    51                 int w1 = dp1[i + 1][j];
    52                 addIt(w1, MOD - dp1[i][j]);
    53                 int w2 = dp2[i + 1][j];
    54                 if (j == 1023) { //delete the case T is empty
    55                     addIt(w2, MOD - 1);
    56                 }
    57                 addIt(ans, 1LL * w1 * w2 % MOD);
    58             }
    59         }
    60         cout << ans << endl;
    61     }
    62 }

    1006

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <map>
      7 using namespace std;
      8 
      9 const int MAX_N = int(1e5) + 10;
     10 int a[MAX_N], n;
     11 
     12 struct Tree {
     13     Tree*pl, *pr;
     14     int l, r;
     15 
     16     pair<int, int> mx; //value,position
     17 
     18     bool same;
     19     int samev;
     20 
     21     void update() {
     22         mx = max(pl->mx, pr->mx);
     23     }
     24 
     25     void apply(int v) {
     26         same = true;
     27         samev = v;
     28         mx = make_pair(v, l);
     29     }
     30 
     31     void relax() {
     32         if (same) {
     33             pl->apply(samev);
     34             pr->apply(samev);
     35             same = false;
     36         }
     37     }
     38 
     39     Tree(int l, int r) :
     40         l(l), r(r) {
     41         same = false;
     42         if (l + 1 == r) {
     43             mx = make_pair(a[l], l);
     44             return;
     45         }
     46         pl = new Tree(l, l + r >> 1);
     47         pr = new Tree(l + r >> 1, r);
     48         update();
     49     }
     50 
     51     void change(int L, int R, int x) {
     52         if (L <= l && R >= r) {
     53             apply(x);
     54             return;
     55         }
     56         if (L >= r || l >= R)
     57             return;
     58         relax();
     59         pl->change(L, R, x);
     60         pr->change(L, R, x);
     61         update();
     62     }
     63 
     64     pair<int, int> query(int L, int R) {
     65         if (L <= l && R >= r) {
     66             return mx;
     67         }
     68         if (L >= r || l >= R)
     69             return make_pair(-1, 0);
     70         relax();
     71         return max(pl->query(L, R), pr->query(L, R));
     72     }
     73 
     74     void print(int a[]) {
     75         if (l + 1 == r) {
     76             a[l] = mx.first;
     77             return;
     78         }
     79         relax();
     80         pl->print(a), pr->print(a);
     81     }
     82 }*rt;
     83 
     84 struct Cover {
     85     map<int, int> mp;
     86 
     87     void init(int l, int r, int init) { //[l,r)
     88         mp[l] = mp[r] = init;
     89     }
     90 
     91     int get_value(int x) {
     92         map<int, int>::iterator it = --mp.upper_bound(x);
     93         int v = it->second;
     94         int l = it->first;
     95         int r = (++it)->first;
     96 //        return make_tuple(v, l, r);
     97         return v;
     98     }
     99 
    100     pair<int, int> get_range(int x) {
    101         map<int, int>::iterator it = --mp.upper_bound(x);
    102         int v = it->second;
    103         int l = it->first;
    104         int r = (++it)->first;
    105 //        return make_tuple(v, l, r);
    106 //        return v;
    107         return make_pair(l, r);
    108     }
    109 
    110     void cover(int l, int r, int w) {
    111         //[l,r)
    112 //        int old = ::get<0>(get(r));
    113         int old = get_value(r);
    114         mp.erase(mp.lower_bound(l), mp.upper_bound(r));
    115         mp[l] = w;
    116         mp[r] = old;
    117     }
    118 };
    119 
    120 int main() {
    121     int T;
    122     cin >> T;
    123     while (T--) {
    124         cin >> n;
    125         Cover cv;
    126         cv.init(0, n, 0);
    127         for (int i = 0; i < n; ++i) {
    128             cin >> a[i];
    129             cv.cover(i, i + 1, a[i]);
    130         }
    131         rt = new Tree(0, n);
    132 
    133         int Q;
    134         cin >> Q;
    135         while (Q--) {
    136             int t, l, r, x;
    137             cin >> t >> l >> r >> x;
    138             --l;
    139             if (t == 1) {
    140                 rt->change(l, r, x);
    141                 cv.cover(l, r, x);
    142             } else {
    143                 for (;;) {
    144                     pair<int, int> mx = rt->query(l, r);
    145                     if (mx.first <= x)
    146                         break;
    147                     pair<int, int> t = cv.get_range(mx.second);
    148                     int L = t.first, R = t.second; //[l,r)
    149                     L = max(L, l);
    150                     R = min(R, r);
    151                     int v = __gcd(mx.first, x);
    152                     rt->change(L, R, v);
    153                     cv.cover(L, R, v);
    154                 }
    155             }
    156         }
    157         rt->print(a);
    158         for (int i = 0; i < n; ++i) {
    159             cout << a[i] << " ";
    160         }
    161         cout << endl;
    162     }
    163 }

    1007

       首先我们不妨枚举所有点的距离标号,> k的就看成k + 1就可以了。 然后考虑一个距离标号为b的点。

       对于一个标号为a的点,如果a < b,那么a到b的边要≥ b − a,并且需要存在一个点使得那条边是b − a。

       这个可以用dp来计算方案数。 当然这样复杂度还是不够,注意到其实没必要枚举点的具体标号,只要分别枚举每种标号的点有几个就可以了。

       ADD

       有多项式算法吗?

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 using namespace std;
      7 
      8 const int MAX_N = 10 + 10;
      9 const int MOD = int(1e9) + 7;
     10 int n, k, L;
     11 int cnt[MAX_N];
     12 int comb[MAX_N][MAX_N];
     13 int pw[MAX_N * MAX_N];
     14 
     15 int ans;
     16 
     17 void addIt(int&x, int c) {
     18     x += c;
     19     if (x >= MOD)
     20         x -= MOD;
     21 }
     22 
     23 int calcDp(int i) {
     24     int dp[MAX_N][2] = { };
     25     int o = 0;
     26     dp[o][0] = 1;
     27 
     28     for (int j = 0; j < i; ++j) {
     29         for (int it = 0; it < cnt[j]; ++it) {
     30             int minL = i - j;
     31             if (minL > L)
     32                 return 0;
     33             int upd[2] = { L - minL, 1 };
     34             for (int u = 0; u < 2; ++u) {
     35                 for (int v = 0; v < 2; ++v) {
     36                     addIt(dp[o + 1][u | v], 1LL * dp[o][u] * upd[v] % MOD);
     37                 }
     38             }
     39             ++o;
     40         }
     41     }
     42 
     43 //        w *= dp[o][1];
     44     int one = dp[o][1];
     45     if (i == k + 1)
     46         addIt(one, dp[o][0]);
     47 
     48     return one;
     49 }
     50 
     51 int calc() {
     52     int w = 1; //calculate the way
     53     int rem = n - 2;
     54     for (int i = 1; i <= k + 1; ++i) {
     55         int need = cnt[i];
     56         if (i == k)
     57             --need;
     58         w = 1LL * w * comb[rem][need] % MOD;
     59         rem -= need;
     60     }
     61 
     62 //    for (int i = 0; i <= k + 1; ++i) {
     63 //        cout << cnt[i] << " ";
     64 //    }
     65 //    cout << endl;
     66 
     67     //calcualte the way to put it
     68     for (int i = 1; i <= k + 1; ++i)
     69         if (cnt[i] > 0) {
     70             int dp[MAX_N][2] = { };
     71             int o = 0;
     72             dp[o][0] = 1;
     73 
     74             for (int j = 0; j < i; ++j) {
     75                 for (int it = 0; it < cnt[j]; ++it) {
     76                     int minL = i - j;
     77                     if (minL > L)
     78                         return 0;
     79                     int upd[2] = { L - minL, 1 };
     80                     for (int u = 0; u < 2; ++u) {
     81                         for (int v = 0; v < 2; ++v) {
     82                             addIt(dp[o + 1][u | v],
     83                                   1LL * dp[o][u] * upd[v] % MOD);
     84                         }
     85                     }
     86                     ++o;
     87                 }
     88             }
     89 
     90 //        w *= dp[o][1];
     91             int one = dp[o][1];
     92             if (i == k + 1)
     93                 addIt(one, dp[o][0]);
     94 
     95             int t = cnt[i];
     96 
     97             for (int j = 0; j < t; ++j) {
     98                 w = 1LL * w * one % MOD;
     99             }
    100             w = 1LL * w * pw[t * (t - 1) / 2] % MOD;
    101         }
    102 //    ans +=
    103 //    addIt(ans, w);
    104     return w;
    105 }
    106 
    107 void search(int at, int rem, int w) {
    108     if (at == k + 2) {
    109         if (rem == 0) {
    110             addIt(ans, w);
    111 //            cout << w << " " << calc() << endl;
    112         }
    113         return;
    114     }
    115     int one = calcDp(at);
    116     if (at != k) {
    117         for (int now = 0; now <= rem; ++now) {
    118             cnt[at] = now;
    119             search(at + 1, rem - now, 1LL * w * comb[rem][now] % MOD);
    120             w = 1LL * w * one % MOD * pw[now] % MOD;
    121             if (w == 0)
    122                 break;
    123         }
    124     } else {
    125         w = 1LL * w * one % MOD;
    126 
    127         for (int now = 0; now <= rem; ++now) {
    128             cnt[at] = now + 1;
    129             search(at + 1, rem - now, 1LL * w * comb[rem][now] % MOD);
    130             w = 1LL * w * one % MOD * pw[now + 1] % MOD;
    131             if (w == 0)
    132                 break;
    133         }
    134     }
    135 }
    136 
    137 int main() {
    138     for (int i = 0; i < MAX_N; ++i) {
    139         for (int j = 0; j <= i; ++j) {
    140             comb[i][j] =
    141                 (i == 0 || j == 0) ?
    142                 1 : (comb[i - 1][j] + comb[i - 1][j - 1]) % MOD;
    143         }
    144     }
    145 
    146     int T;
    147     scanf("%d",&T);
    148     while (T--) {
    149         scanf("%d %d %d",&n,&k,&L);
    150 
    151         pw[0] = 1;
    152         for (int i = 1; i <= n * n; ++i) {
    153             pw[i] = 1LL * pw[i - 1] * L % MOD;
    154         }
    155 
    156         memset(cnt, 0, sizeof cnt);
    157         ans = 0;
    158         cnt[0] = 1;
    159         search(1, n - 2, 1);
    160 
    161         printf("%d
    ",ans);
    162     }
    163 }

    1008

       如果知道了该点离a,b中的a近一点,这实际上意味着确定了一个半平面,左侧是该点可能的区域。

       我们不妨枚举离该点第二近的是哪个,再枚举第一近的是哪个,然后平面切割出这种情况下的多边形。

       然后进行简单的积分就能计算出答案了。

       ADD

       第k远当然也是可做的。

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <vector>
      8 using namespace std;
      9 
     10 const double EPS = 1e-8;
     11 inline int sign(double a) {
     12     return a < -EPS ? -1 : a > EPS;
     13 }
     14 
     15 struct Point {
     16     double x, y;
     17     Point() {
     18     }
     19     Point(double _x, double _y) :
     20         x(_x), y(_y) {
     21     }
     22     Point operator+(const Point&p) const {
     23         return Point(x + p.x, y + p.y);
     24     }
     25     Point operator-(const Point&p) const {
     26         return Point(x - p.x, y - p.y);
     27     }
     28     Point operator*(double d) const {
     29         return Point(x * d, y * d);
     30     }
     31     Point operator/(double d) const {
     32         return Point(x / d, y / d);
     33     }
     34     bool operator<(const Point&p) const {
     35         int c = sign(x - p.x);
     36         if (c)
     37             return c == -1;
     38         return sign(y - p.y) == -1;
     39     }
     40     double dot(const Point&p) const {
     41         return x * p.x + y * p.y;
     42     }
     43     double det(const Point&p) const {
     44         return x * p.y - y * p.x;
     45     }
     46     double alpha() const {
     47         return atan2(y, x);
     48     }
     49     double distTo(const Point&p) const {
     50         double dx = x - p.x, dy = y - p.y;
     51         return hypot(dx, dy);
     52     }
     53     double alphaTo(const Point&p) const {
     54         double dx = x - p.x, dy = y - p.y;
     55         return atan2(dy, dx);
     56     }
     57     void read() {
     58         scanf("%lf%lf", &x, &y);
     59     }
     60     double abs() {
     61         return hypot(x, y);
     62     }
     63     double abs2() {
     64         return x * x + y * y;
     65     }
     66     void write() {
     67         cout << "(" << x << "," << y << ")" << endl;
     68     }
     69     Point rot90() {
     70         return Point(-y, x);
     71     }
     72 };
     73 
     74 #define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
     75 
     76 #define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
     77 
     78 Point isSS(Point p1, Point p2, Point q1, Point q2) {
     79     double a1 = cross(q1,q2,p1), a2 = -cross(q1,q2,p2);
     80     return (p1 * a2 + p2 * a1) / (a1 + a2);
     81 }
     82 
     83 vector<Point> convexCut(const vector<Point>&ps, Point q1, Point q2) {
     84     vector<Point> qs;
     85     int n = ps.size();
     86     for (int i = 0; i < n; ++i) {
     87         Point p1 = ps[i], p2 = ps[(i + 1) % n];
     88         int d1 = crossOp(q1,q2,p1), d2 = crossOp(q1,q2,p2);
     89         if (d1 >= 0)
     90             qs.push_back(p1);
     91         if (d1 * d2 < 0)
     92             qs.push_back(isSS(p1, p2, q1, q2));
     93     }
     94     return qs;
     95 }
     96 
     97 double calcArea(const vector<Point>&ps) {
     98     int n = ps.size();
     99     double ret = 0;
    100     for (int i = 0; i < n; ++i) {
    101         ret += ps[i].det(ps[(i + 1) % n]);
    102     }
    103     return ret / 2;
    104 }
    105 
    106 vector<Point> convexHull(vector<Point> ps) {
    107     int n = ps.size();
    108     if (n <= 1)
    109         return ps;
    110     sort(ps.begin(), ps.end());
    111     vector<Point> qs;
    112     for (int i = 0; i < n; qs.push_back(ps[i++])) {
    113         while (qs.size() > 1 && crossOp(qs[qs.size()-2],qs.back(),ps[i]) <= 0)
    114             qs.pop_back();
    115     }
    116     for (int i = n - 2, t = qs.size(); i >= 0; qs.push_back(ps[i--])) {
    117         while (qs.size() > t && crossOp(qs[qs.size()-2],qs.back(),ps[i]) <= 0)
    118             qs.pop_back();
    119     }
    120     qs.pop_back();
    121     return qs;
    122 }
    123 
    124 typedef vector<Point> Poly;
    125 
    126 Poly background(double X, double Y) { //[0,X] * [0,Y]
    127     Poly ret;
    128     ret.push_back(Point(0, 0));
    129     ret.push_back(Point(X, 0));
    130     ret.push_back(Point(X, Y));
    131     ret.push_back(Point(0, Y));
    132     return ret;
    133 }
    134 
    135 const int MAX_N = 100 + 1;
    136 
    137 Poly BIG;
    138 int n, X, Y;
    139 Point ps[MAX_N];
    140 
    141 Poly getNear(Poly ps, Point a, Point b) { //get the part near a
    142     Point p1 = (a + b) / 2, p2 = p1 + (b - a).rot90();
    143     return convexCut(ps, p1, p2);
    144 }
    145 
    146 double cut(Poly ps, double x) {
    147     double ly = 1e100, ry = -1e100;
    148     for (int i = 0; i < ps.size(); ++i) {
    149         Point p1 = ps[i], p2 = ps[(i + 1) % ps.size()];
    150         if (p1.x > p2.x)
    151             swap(p1, p2);
    152         if (sign(x - p1.x) >= 0 && sign(p2.x - x) >= 0) {
    153             double a = x - p1.x, b = p2.x - x;
    154             double y = (b * p1.y + a * p2.y) / (a + b);
    155             ly = min(ly, y);
    156             ry = max(ry, y);
    157         }
    158     }
    159     return ry - ly;
    160 }
    161 
    162 double sqr(double x) {
    163     return x * x;
    164 }
    165 
    166 double calc(Poly ps, double x) {
    167     vector<double> ix;
    168     for (int i = 0; i < ps.size(); ++i) {
    169         ix.push_back(ps[i].x);
    170     }
    171     sort(ix.begin(), ix.end());
    172     double ret = 0;
    173     for (int i = 0; i + 1 < ix.size(); ++i) {
    174         double l = ix[i], r = ix[i + 1];
    175         double m1 = (l * 2 + r) / 3, m2 = (l + r * 2) / 3;
    176         double v = sqr(l - x) * cut(ps, l) + sqr(m1 - x) * cut(ps, m1) * 3
    177                    + sqr(m2 - x) * cut(ps, m2) * 3 + sqr(r - x) * cut(ps, r);
    178         v /= 8;
    179         v *= r - l;
    180         ret += v;
    181     }
    182     return ret;
    183 }
    184 
    185 double integrate(Poly ps, Point p) {
    186     double ret = calc(ps, p.x);
    187     for (int i = 0; i < ps.size(); ++i) {
    188         swap(ps[i].x, ps[i].y);
    189     }
    190     ret += calc(ps, p.y);
    191     return ret;
    192 }
    193 
    194 int main() {
    195     int T;
    196     scanf("%d",&T);
    197     while (T--) {
    198         scanf("%d %d %d",&n,&X,&Y);
    199         BIG = background(X, Y);
    200         for (int i = 0; i < n; ++i) {
    201             ps[i].read();
    202         }
    203 
    204         double sum = 0;
    205 
    206         for (int second = 0; second < n; ++second) {
    207             for (int first = 0; first < n; ++first)
    208                 if (first != second) {
    209                     Poly py = BIG;
    210                     py = getNear(py, ps[first], ps[second]);
    211                     for (int i = 0; i < n; ++i)
    212                         if (i != first && i != second) {
    213                             py = getNear(py, ps[second], ps[i]);
    214                             if (calcArea(py) <= 1e-8)
    215                                 break;
    216                         }
    217                     sum += integrate(py, ps[second]);
    218                 }
    219         }
    220 
    221         printf("%0.10lf
    ", sum / X / Y);
    222     }
    223 }

    1009

       四边形不等式优化存在一定问题,暂时没有解法

     

    1010

       和C类似,直接存到目前为止,哪些数可以被拼出来。

       ADD

       有更好的做法吗?

     

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <string>
     6 using namespace std;
     7 int n, k, L;
     8 
     9 const int MAX_K = 20, MOD = int(1e9) + 7;
    10 
    11 void addIt(int&x, int c) {
    12     x += c;
    13     if (x >= MOD)
    14         x -= MOD;
    15 }
    16 
    17 int dp[1 << MAX_K];
    18 
    19 int main() {
    20     int T;
    21     scanf("%d",&T);
    22     while (T--) {
    23         scanf("%d %d %d",&n,&k,&L);
    24         memset(dp, 0, sizeof dp);
    25         dp[0] = 1;
    26         int extra = 0;
    27         if (L > k) {
    28             extra = L - k;
    29             L = k;
    30         } else {
    31         }
    32         int mask = (1 << k) - 1;
    33         for (int i = 0; i < n; ++i) {
    34             for (int j = (1 << k) - 1; j >= 0; --j) {
    35                 int c = dp[j];
    36                 if (c == 0)
    37                     continue;
    38                 for (int o = 1; o <= L; ++o) {
    39                     int nj = j | ((j << o) & mask) | (1 << (o - 1));
    40 //                dp[nj] += c;
    41                     addIt(dp[nj], c);
    42                 }
    43                 addIt(dp[j], 1LL * c * extra % MOD);
    44             }
    45         }
    46         int ans = 0;
    47         for (int i = 0; i < (1 << k); ++i) {
    48             if (i >> (k - 1) & 1)
    49                 addIt(ans, dp[i]);
    50         }
    51         cout << ans << endl;
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    二分查找经典题型
    部队侦察
    取随机数函数的使用
    猜拳游戏
    Learning C Struct
    Linux shell get random number
    Linux Bash shell one practice : array if else
    Linux shell misc
    Bash Shell read file line by line and substring
    storm的并发和消息保障性
  • 原文地址:https://www.cnblogs.com/jams-jellies/p/3884053.html
Copyright © 2011-2022 走看看