2016.4.23 浙江省赛题解

Apples and Ideas

Time Limit: 2 Seconds       Memory Limit: 65536 KB

"If you have an apple and I have an apple and we exchange these apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas." - George Bernard Shaw

Now Alice has A apples and B ideas, while Bob has C apples and D ideas, what will they have if they exchange all things?

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The only line contains four integers A, B, C, D (0 <= A, B, C, D <= 100) - as the problem described.

Output

For each test case, output two lines. First line contains two integers, indicating the number of Alice's apples and ideas; second line contains two integers, indicating the number of Bob's apples and ideas.

Sample Input

4
0 0 5 30
20 25 20 0
20 25 20 15
20 25 25 30

Sample Output

5 30
0 30
20 25
20 25
20 40
20 40
25 55
20 55


A. APPLES AND IDEAS

A,C=C,A; B=D=B+D;

#include 
using namespace std;

int main() {
  int T; cin >> T;
  for (int _ = 0; _ < T; ++_ ) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    cout << c << " " << b + d << endl;
    cout << a << " " << b + d << endl;
  }
  return 0;
}


More Health Points

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Recently, Bright Luna is playing a massively multiplayer online role-playing game (MMORPG) called Legendary Age. Designers of this game prepared many mini-games during daily operations. Players can ignore these games without any loss. If you spend some time in them, you can always obtain some bonuses. This is one of the fascinating features ofLegendary Age.

One day, Bright Luna had a fight with other players. After that he came back to the city to recover his Health Points (HP). Surprisingly, the NPC gave him a special choice. The NPC can teleport Bright Luna to a colorful fantasy world with N dungeons. These dungeons are identified from 1 through N. Each dungeon has exactly a one-way exit leading to another dungeon which has a smaller identifier except for the dungeon 1, which has no exit.

There is a buff or debuff in each dungeon which can be described by an integer Bi. Bright Luna will get the i-th buff/debuff when he enters the i-th dungeon. When he leaves a dungeon or leaves the world, the buffs/debuffs he has obtained will change his HP by Bi. For example, If he already visited the dungeons 6 -> 4 -> 3, when he leaves the dungeon 3, his HP will be changed by (B6 + B4 + B3). The buffs/debuffs will not expire until he completes the adventure.

The NPC had shown the world map to Bright Luna. Bright Luna can choose the dungeon he enters at the beginning and he can leave the world at any dungeon. Of course, he can refuse to take this adventure. Can you help Bright Luna to gain as many health points as possible?

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases. For each test case:

The first line contains an integer N (1 ≤ N ≤ 105).

The second line contains N integers Bi (|Bi| ≤ 108).

The third line contains N - 1 integers Fi (2 ≤ i ≤ N, Fi < i) indicating the dungeons which the exit of dungeon i lead to.

Output

For each case, please output the maximum health points Bright Luna can gain.

Sample Input

4
4
1 4 3 2
1 1 1
4
1 2 -3 4
1 2 3
4
-4 2 -3 4
1 2 3
3
-1 -2 -3
1 1

Sample Output

9
12
8
0

Hint

In the first example, we can start from dungeon 2 and end at dungeon 1.

In the second example, we can start from dungeon 4 and end at dungeon 1.

In the third example, we can start from dungeon 4 and end at dungeon 2.

B. MORE HEALTH POINTS

考虑链上的版本(其实就是Bear and Bowling 4),给出nn个数a_1,a_2,...,a_na1,a2,...,an,求出\sum\limits_{i=l}^{r}{(i-l+1)a_i}i=lr(il+1)ai的最大值。令s_i=\sum\limits_{j=1}^{i}a_j, p_i=\sum\limits_{j=1}^{i}ja_jsi=j=1iaj,pi=j=1ijaj,那么就是求p_r-p_{l-1}-l(s_r-s_{l-1})prpl1l(srsl1)的最大值。如果固定rr,把式子变换一下就是找到一个ll最大化p_r-ls_r-p_{l-1}+ls_{l-1}prlsrpl1+lsl1,维护一个凸壳就可以搞了。推广到树上把链上用到的单调队列可持久一下就好了,复杂度O(n\log n)O(nlogn)

也可以树分治。考虑每次分治中心gg,一条合法的在原来有根树上的路径是这么组成的:gg往下标号一路递减的路径+gg往下标号一路递增的路径。类似地,推一下合并需要的式子,会发现也是可以用凸壳维护的,复杂度O(n\log^2n)O(nlog2n)

#include 
using namespace std;
typedef long long LL;

class Solution {
  static const int MAXN = 100000 + 10;
  static const LL inf = 1ll << 60;
  vector G[MAXN];
  int w[MAXN], n;

  struct Line {// m * x + b
    LL m, b;
    double inter(const Line &r) const {
      return (r.b - b) / (m - r.m);
    }
    inline LL eval(LL x) {return m * x + b;}
  } Q[MAXN];

  int rt, mins, total, top;
  int vs[MAXN], sz[MAXN], dep[MAXN];
  LL val[MAXN], ps[MAXN], ret;

  void getCenter(int u, int f = -1) {
    int mx = 0; sz[u] = 1;
    for (auto &v: G[u]) if (v != f && !vs[v]) {
      getCenter(v, u); sz[u] += sz[v];
      mx = max(mx, sz[v]);
    }
    mx = max(mx, total - sz[u]);
    if (mx < mins) mins = mx, rt = u;
  }
  int dfs1(int u, int d = 1) {
    ret = max(ret, val[d]);
    for (auto &v: G[u]) if (!vs[v] && u > v) {
      ps[v] = ps[u] + w[v];
      val[d + 1] = val[d] + ps[v];
      return dfs1(v, d + 1) + 1;
    }
    return 1;
  }
  void dfs2(int u, int d = 0, LL sum = 0) {
    sum += 1ll * d * w[u];
    // max(ps[u] * m + b + sum)
    int left = 0, right = top - 2;
    while (left < right) {
      int mid = (left + right) >> 1;
      if (Q[mid].eval(ps[u]) >= Q[mid + 1].eval(ps[u])) right = mid;
      else left = mid + 1;
    }
    ret = max(ret, Q[left].eval(ps[u]) + sum);
    if (left + 1 < top) ret = max(ret, Q[left + 1].eval(ps[u]) + sum);
    for (auto &v: G[u]) if (!vs[v] && u < v) {
      ps[v] = ps[u] + w[v];
      dfs2(v, d + 1, sum);
    }
  }
  void solve(int u, int _tot) {
    total = _tot; mins = _tot * 2;
    getCenter(u); u = rt; vs[u] = 1; getCenter(u);
    val[1] = ps[u] = w[u];
    int md = dfs1(u);
    top = 0;
    for (int i = 1; i <= md; ++i) {
      Line now = (Line){i, val[i]};
      while (top >= 2 && Q[top - 2].inter(Q[top - 1]) >= Q[top - 1].inter(now)) --top;
      Q[top++] = now;
    }
    ps[u] = 0; dfs2(u);
    for (int i = 0; i <= md; ++i) val[i] = -inf;
    for (auto &v: G[u]) if (!vs[v]) {
      solve(v, sz[v]);
    }
  }

public:
  void run() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
      scanf("%d", w + i); G[i].clear();
    }
    for (int i = 1; i < n; ++i) {
      int x; scanf("%d", &x); --x;
      G[x].push_back(i);
      G[i].push_back(x);
    }
    ret = 0;
    for (int i = 0; i < n; ++i) val[i] = -inf;
    memset(vs, 0, sizeof(vs[0]) * n);
    solve(0, n);
    printf("%lld\n", ret);
  }
} sol;

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) sol.run();
  return 0;
}


Defuse the Bomb

Time Limit: 2 Seconds       Memory Limit: 65536 KB

The bomb is about to explode! Please defuse it as soon as possible!

There is a display showing a number from 1 to 4 on the bomb. Besides this, there are 4 buttons under the display. Each button is labeled by a number from 1 to 4. The numbers on the buttons are always distinct.

There are 5 defusing stages in total. Pressing the correct button can progress the bomb to the next defusing stage. The number on the display and the number on each button may be different in different stages. The bomb will be defused only when all 5 defusing stages get passed. Pressing the incorrect button will cause the bomb to explode immediately. Be careful!

Here is the detailed bomb defusing manual. Button positions are ordered from left to right.

Stage 1:

  • If the display is 1, press the button in the second position.
  • If the display is 2, press the button in the second position.
  • If the display is 3, press the button in the third position.
  • If the display is 4, press the button in the fourth position.

Stage 2:

  • If the display is 1, press the button labeled "4".
  • If the display is 2, press the button in the same position as you pressed in stage 1.
  • If the display is 3, press the button in the first position.
  • If the display is 4, press the button in the same position as you pressed in stage 1.

Stage 3:

  • If the display is 1, press the button with the same label you pressed in stage 2.
  • If the display is 2, press the button with the same label you pressed in stage 1.
  • If the display is 3, press the button in the third position.
  • If the display is 4, press the button labeled "4".

Stage 4:

  • If the display is 1, press the button in the same position as you pressed in stage 1.
  • If the display is 2, press the button in the first position.
  • If the display is 3, press the button in the same position as you pressed in stage 2.
  • If the display is 4, press the button in the same position as you pressed in stage 2.

Stage 5:

  • If the display is 1, press the button with the same label you pressed in stage 1.
  • If the display is 2, press the button with the same label you pressed in stage 2.
  • If the display is 3, press the button with the same label you pressed in stage 4.
  • If the display is 4, press the button with the same label you pressed in stage 3.

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases. For each test case:

There are 5 lines. Each line contains 5 integers D, B1, B2, B3, B4 indicating the number on the display and the numbers on the buttons respectively. The i-th line correspond to the i-th stage.

Output

For each test case, output 5 lines. The i-th line contains two integers indicating the position and the label of the correct button for the i-th stage.

Sample Input

1
4 2 1 3 4
2 2 4 3 1
4 3 1 4 2
4 3 4 2 1
2 3 1 2 4

Sample Output

4 4
4 1
3 4
4 1
2 1

Hint

Keep talking with your teammates and nobody explodes!

C. DEFUSE THE BOMB

按照题目意思模拟。

#include 
using namespace std;
typedef pair PII;

vector res;
int b[5][5], a[5];

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) {
    int r[5];
    for (int i = 0; i < 5; ++i) {
      for (int j = 0; j < 5; ++j) {
        cin >> b[i][j];
      }
    }
    // stage 1
    int *x = b[0], d = x[0];
    if (d <= 2) r[0] = 2;
    else r[0] = d;
    // stage 2
    x = b[1], d = x[0];
    for (int i = 1; i < 5; ++i) a[x[i]] = i;
    if (d == 1) r[1] = a[4];
    else if (d == 3) r[1] = 1;
    else r[1] = r[0];
    // stage 3
    x = b[2], d = x[0];
    for (int i = 1; i < 5; ++i) a[x[i]] = i;
    if (d == 1) r[2] = a[b[1][r[1]]];
    else if (d == 2) r[2] = a[b[0][r[0]]];
    else if (d == 4) r[2] = a[4];
    else r[2] = d;
    // stage 4
    x = b[3], d = x[0];
    if (d == 1) r[3] = r[0];
    else if (d == 2) r[3] = 1;
    else r[3] = r[1];
    // stage 5
    x = b[4], d = x[0];
    for (int i = 1; i < 5; ++i) a[x[i]] = i;
    if (d <= 2) r[4] = a[b[d - 1][r[d - 1]]];
    else r[4] = a[b[6 - d][r[6 - d]]];
    for (int i = 0; i < 5; ++i) {
      cout << r[i] << " " << b[i][r[i]] << endl;
    }
  }
  return 0;
}


The Lucky Week

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Edward, the headmaster of the Marjar University, is very busy every day and always forgets the date.

There was one day Edward suddenly found that if Monday was the 1st, 11th or 21st day of that month, he could remember the date clearly in that week. Therefore, he called such week "The Lucky Week".

But now Edward only remembers the date of his first Lucky Week because of the age-related memory loss, and he wants to know the date of the N-th Lucky Week. Can you help him?

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases. For each test case:

The only line contains four integers Y, M, D and N (1 ≤ N ≤ 109) indicating the date (Y: year, M: month, D: day) of the Monday of the first Lucky Week and the Edward's query N.

The Monday of the first Lucky Week is between 1st Jan, 1753 and 31st Dec, 9999 (inclusive).

Output

For each case, print the date of the Monday of the N-th Lucky Week.

Sample Input

2
2016 4 11 2
2016 1 11 10

Sample Output

2016 7 11
2017 9 11


D. THE LUCKY WEEK

可以观察到1753年1月1日是周一,然后我们知道大概再过2800年就会重复。于是预处理出1753.01.01后面2800年的所有lucky week。之后根据循环节算一下就好了。

#include 
using namespace std;

vector> p;

int day(int y, int m, int d) {
  int tm = m >= 3 ? (m - 2) : (m + 10);
  int ty = m >= 3 ? y : (y - 1);
  return (ty + ty / 4 - ty / 100 + ty / 400 + (int)(2.6 * tm - 0.2) + d) % 7;
}

void run() {
  int y, m, d, n; cin >> y >> m >> d >> n;
  y -= 1753; n += y / 2800 * p.size();
  y %= 2800;
  n += lower_bound(p.begin(), p.end(), make_tuple(y, m, d)) - p.begin() - 1;
  auto res = p[n % p.size()];
  y = get<0>(res);
  m = get<1>(res);
  d = get<2>(res);
  y += n / p.size() * 2800 + 1753;
  cout << y << " " << m << " " << d << endl;
}

int main() {
  cerr << day(1753, 1, 1) << endl;
  for (int y = 0; y < 2800; ++y) {
    for (int m = 1; m <= 12; ++m) {
      if (day(y + 1753, m,  1) == 1) p.push_back(make_tuple(y, m,  1));
      if (day(y + 1753, m, 11) == 1) p.push_back(make_tuple(y, m, 11));
      if (day(y + 1753, m, 21) == 1) p.push_back(make_tuple(y, m, 21));
    }
  }
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) run();
  return 0;
}



Modulo Query

Time Limit: 2 Seconds       Memory Limit: 65536 KB

One day, Peter came across a function which looks like:

  • F(1, X) = X mod A1.
  • F(i, X) = F(i - 1, X) mod Ai, 2 ≤ i ≤ N.
Where  A  is an integer array of length  N X  is a non-negative integer no greater than  M .

Peter wants to know the number of solutions for equation F(N, X) = Y, where Y is a given number.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integers N and M (2 ≤ N ≤ 105, 0 ≤ M ≤ 109).

The second line contains N integers: A1, A2, ..., AN (1 ≤ Ai ≤ 109).

The third line contains an integer Q (1 ≤ Q ≤ 105) - the number of queries. Each of the following Q lines contains an integer Yi (0 ≤ Yi ≤ 109), which means Peter wants to know the number of solutions for equation F(N, X) = Yi.

Output

For each test cases, output an integer S = (1 ⋅ Z1 + 2 ⋅ Z2 + ... + Q ⋅ ZQ) mod (109 + 7), where Zi is the answer for the i-th query.

Sample Input

1
3 5
3 2 4
5
0
1
2
3
4

Sample Output

8

Hint

The answer for each query is: 4, 2, 0, 0, 0.


E. MODULO QUERY

可以观察到一个区间对一个数取模后的结果也可以用区间来表示,并且这些区间的左端点都是0。于是直接用一个map存每次取模之后的区间和这个区间出现次数,要取模的时候,找出所有右端点大于等于当前模数的所有区间,暴力算一下结果即可。对于查询,二分下位置,求个后缀和就好了。下面分析下复杂度为什么是对的。

众所周知:一个数对一堆数取模,最多会有\loglog次值的改变。对于这题每对一个新数取模,最多只会增加一个区间。考虑当前区间是[0,v_i][0,vi],要对xx取模,那么对于v_i < xvi<x的区间没有变化,对于v_i \ge xvix的那些区间会变成[0,v_i \text{ mod } x][0,vi mod x],并且可能会新增区间[0,x-1][0,x1]。这个过程其实相当于每个a_iai对后面所有数依次取模,那么总共会有O(n \log n)O(nlogn)次值的改变,每次改变需要在map上修改一下,总复杂度是O(n\log^2n)O(nlog2n)的。

#include 
using namespace std;
const int MAXN = 100000 + 10, M = 1e9 + 7;
int a[MAXN], n, m;
map last;

void run() {
  scanf("%d%d", &n, &m);
  last.clear(); last[m] = 1;
  for (int i = 0; i < n; ++i) {
    int x, s = 0; scanf("%d", &x);
    auto it = last.lower_bound(x);
    for (; it != last.end(); ) {
      last[it->first % x] += it->second;
      s += it->second * (it->first / x);
      it = last.erase(it);
    }
    if (s) last[x - 1] += s;
  }
  int s = 0;
  for (auto it = last.rbegin(); it != last.rend(); ++it) {
    it->second += s; s = it->second;
  }
  int q, ret = 0; scanf("%d", &q);
  for (int i = 1; i <= q; ++i) {
    int x; scanf("%d", &x);
    auto it = last.lower_bound(x);
    if (it != last.end()) ret += 1ll * it->second * i % M;
    if (ret >= M) ret -= M;
  }
  printf("%d\n", ret);
}

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) run();
  return 0;
}


Kpop Music Party

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Marjar University often hosts Kpop music festival. A Kpop music festival will last several days. During a Kpop festival, there will be a Kpop party every day. Kpop music is very popular all over the world, so there may be more than one Kpop music festival being hosted simultaneously.

Edward, the headmaster of Marjar University, is always obsessed with Kpop music. He will be very excited continuously for K days after attending a Kpop music party. More specifically, If he attends a Kpop party in the i-th day, he would be very excited from the i-th day to the (i + K - 1)-th day (inclusive). But the excitatory state does not stack. For example, if K is 5 and Edward attended a party in Day 1 and a party in Day 3, he will be very excited only from Day 1 to Day 7.

Edward has got the schedule of N Kpop music festivals in Marjar University. Each Kpop music festival lasts one or more days. The i-th Kpop festival starts at the Si-th day and ends at the Ei-th day (inclusive). Due to restrictions on the discipline for the headmaster, he can attend at most M Kpop parties. Now he wants to maximize the number of days being excited. Can you help him?

Input

There are multiple test cases. The first line of input is an integer T (≤ 1000) indicating the number of test cases. For each test case:

The first line contains three integers, N, K and M.

The next N lines, each line contains two integers Si and Ei (1 ≤ N ≤ 10, 1 ≤ K, M, Si, Ei ≤ 109).

Output

For each case, print the number of the most days that Edward can be excited for.

Sample Input

2
1 5 2
1 3
3 7 3
1 5
2 5
13 13

Sample Output

7
18

Hint

For the first case, the only Kpop festival lasts from Day 1 to Day 3. Edward can attend a party in Day 1 and a party in Day 3, he would be very excited from Day 1 to Day 7. Edward can be excited for 7 days at most.

For the second case, there are 3 Kpop festivals. Edward can take part in the Kpop parties in Day 1, Day 5 and Day 13. He would be very excited from Day 1 to Day 11 and from Day 13 to Day 19. Edward can be excited for 18 days at most.


F. KPOP MUSIC PARTY

首先把可以合并的区间合并掉,那么剩下来的区间互不相交。考虑到最左端点是一定会参加party的,于是只要考虑每个区间的右端点是否要参加party就好了,这部分可以用O(2^n)O(2n)的复杂度枚举,剩下来直接贪心就好了。

#include 
using namespace std;
typedef pair PII;
const int MAXN = 100 + 10;

PII P[MAXN];
int n, m, k;

void run() {
  cin >> n >> k >> m;
  for (int i = 0; i < n; ++i) {
    cin >> P[i].first >> P[i].second;
  }
  sort(P, P + n);
  int s = 0, ret = 0;
  for (int i = 1; i < n; ++i) {
    if (P[i].first <= P[s].second + 1) {
      P[s].second = max(P[s].second, P[i].second);
    } else P[++s] = P[i];
  }
  n = s + 1; s = 1 << n;
  for (int msk = 0; msk < s; ++msk) {
    int sum = 0, now = 0, rest = m;
    for (int i = 0; i < n && rest; ++i) {
      now = max(now, P[i].first - 1);
      if (now >= P[i].second && (msk >> i & 1)) {
        sum += P[i].second + k - 1 - now;
        now = P[i].second + k - 1;
        rest--;
      } else if (now < P[i].second) {
        int t = min(rest, (P[i].second - now - 1) / k + 1);
        sum += t * k; now += t * k; rest -= t;
        assert(now >= P[i].second || rest == 0);
        if (rest && (msk >> i & 1)) {
          sum += P[i].second + k - 1 - now;
          now = P[i].second + k - 1;
          rest--;
        }
      }
    }
    ret = max(ret, sum);
  }
  cout << ret << endl;
}

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) run();
  return 0;
}

Substring Counting

Time Limit: 2 Seconds       Memory Limit: 65536 KB

A non-empty string S is called binary, if it consists only of characters "0" and "1". A substring S[l...r] (1 ≤ l ≤ r ≤ |S|) of string S = S1S2...S|S| (where |S| is the length of string S) is stringSlSl + 1...Sr.

Peter has got a long binary string S starting with "0", and he wants to know the number of distinct non-empty substrings of the string S that the occurrences of "0" in the substring is exact M, where M is Peter's lucky number. Two substrings S[x...y] and S[p...q] are considered distinct if their content is different, i.e. S[x...y] ≠ S[p...q].

Since the binary string is very long, we will compress it. The compression method is:

  • Split the string to runs of same characters. Any two adjacent runs consist of different characters.
  • Use the length of each run to represent the string.

For example, the runs of a binary string 00101100011110111101001111111 is {00, 1, 0, 11, 000, 1111, 0, 1111, 0, 1, 00, 1111111}, so it will be compressed into {2, 1, 1, 2, 3, 4, 1, 4, 1, 1, 2, 7}.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integers N and M (2 ≤ N ≤ 2000, 0 ≤ M ≤ 109) - the number of runs and Peter's lucky number.

The next line contains N integers: A1, A2, ..., AN (1 ≤ Ai ≤ 106), indicating the length of the each run.

Output

For each test case, output an integer denoting the answer.

Sample Input

1
3 2
3 2 1

Sample Output

4

Hint

The original binary string is 000110, the four substrings are: 00, 001, 0011, 0110.

G. SUBSTRING COUNTING

所有合法的子串除了左右两部分都包含了完整的一些runs(全0的case需要特殊处理下),这些合法的子串具体可以分为3种情况:左右两端都是0,左右两端一个0一个1,左右两端都是1。

  1. 两端都是0:假设左右0的个数分别是aabb,中间0的个数是xx,那么要满足x < m, a+b+x \ge mx<m,a+b+xm。抠出满足这些条件的所有字段,把中间部分相同的归为一类(为了不重复计数)。对于同一类,问题转化为给出若干(a_i,b_i)(ai,bi)和一个整数xx,问有多少(s,t)(s,t)满足存在(a_i,b_i)(ai,bi)使得1 \le s \le a_i, 1 \le t \le b_i, s + t + x=m1sai,1tbi,s+t+x=m。然后对于没对(a_i,b_i)(ai,bi)我们通过上面条件确定ss的范围,之后一个区间并算下有多少可行的ss就好了。

  2. 左端是1右端是0:枚举1所属的那个段,然后往右扩展直到有mm个0为止。同样可以归个类,对于同一个类,计算左侧可以有的1的最大值,这个就是对答案的贡献。左端是0右端是1的情况只要把串reverse一下就好了。

  3. 两端都是1:假设左右1的个数分别是aabb,我们要找出中间0的个数是mm的那些端,类似地,把中间相同的归个类。对于同一类,问题转化为给出若干(a_i,b_i)(ai,bi),问有多少(s,t)(s,t)满足存在(a_i,b_i)(ai,bi)使得1 \le s \le a_i, 1 \le t \le b_i1sai,1tbi。按照a_iai排个序,令c_i=\max(b_i,b_{i+1})ci=max(bi,bi+1),然后这个类对答案的贡献就是\sum c_i(a_i-a_{i-1})ci(aiai1)

还有m=0m=0等一些边界case,特判一下就好了。

#include 
using namespace std;
typedef long long LL;
typedef pair PII;
typedef vector VI;
typedef vector VP;

class Solution {
  static const int MAXN = 2000 + 10;
  int a[MAXN], n, m;
  LL count00(LL ret = 0) {
    map mp;
    for (int i = 1; i < n; i += 2) {
      VI pt; int sum = 0;
      for (int j = i; j + 1 < n; ++j) {
        pt.push_back(a[j]);
        if (j & 1) {
          if (a[i - 1] + sum + a[j + 1] >= m) {
            mp[pt].push_back(PII(a[i - 1], a[j + 1]));
          }
        } else sum += a[j];
        if (sum >= m) break;
      }
    }
    for (auto &e: mp) {
      VP &y = e.second, x;
      int sum = m;
      for (size_t i = 1; i < e.first.size(); i += 2) sum -= e.first[i];
      for (auto &v: y) {
        int L = v.first, R = v.second;
        v.first = max(1, sum - R);
        v.second = min(L, sum - 1);
        if (v.first <= v.second) x.push_back(v);
      }
      if (x.empty()) continue;
      sort(x.begin(), x.end());
      int l = x[0].first, r = x[0].second;
      for (size_t i = 0; i < x.size(); ++i) {
        if (x[i].first <= r) r = max(r, x[i].second);
        else {
          ret += r - l + 1;
          l = x[i].first;
          r = x[i].second;
        }
      }
      ret += r - l + 1;
    }
    return ret;
  }
  LL count10(LL ret = 0) {
    map mp;
    for (int i = 1; i < n; i += 2) {
      VI pt; int sum = 0;
      for (int j = i + 1; j < n; ++j) {
        pt.push_back(a[j]);
        if (~j & 1) {
          sum += a[j];
          if (sum >= m) {
            sum -= a[j];
            pt.pop_back();
            pt.push_back(m - sum);
            mp[pt] = max(mp[pt], a[i]);
            break;
          }
        }
      }
    }
    for (auto &e: mp) ret += e.second;
    return ret;
  }
  LL count11(LL ret = 0) {
    map mp;
    for (int i = 2; i < n; i += 2) {
      VI pt; int sum = 0;
      for (int j = i; j + 1 < n; ++j) {
        pt.push_back(a[j]);
        if (~j & 1) {
          sum += a[j];
          if (sum == m) mp[pt].push_back(PII(a[i - 1], a[j + 1]));
          else if (sum > m) break;
        }
      }
    }
    for (auto &e: mp) {
      VP &y = e.second;
      sort(y.begin(), y.end());
      for (int i = y.size() - 2; i >= 0; --i) {
        y[i].second = max(y[i].second, y[i + 1].second);
      }
      for (size_t i = 0; i < y.size(); ++i) {
        int extra = i ? y[i].first - y[i - 1].first : y[i].first;
        ret += 1ll * extra * y[i].second;
      }
    }
    return ret;
  }
public:
  void run() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) scanf("%d", a + i);
    LL ret = count00() + count11();
    ret += count10();
    if (n % 2 == 0) a[n++] = 0;
    reverse(a, a + n);
    ret += count10();
    for (int i = 0; i < n; i += 2) if (a[i] >= m && m) {
      ++ret; break;
    }
    if (m == 0) {
      ret = 0;
      for (int i = 1; i < n; i += 2) ret = max(ret, (LL)a[i]);
    }
    printf("%lld\n", ret);
  }
} sol;

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) sol.run();
  return 0;
}


Himalayas

Time Limit: 5 Seconds       Memory Limit: 65536 KB

The Himalayas or Himalaya is a mountain range in the Indian subcontinent, which separates the Indo-Gangetic Plain from the Tibetan Plateau. This range is home to nine of the ten highest peaks on Earth, including the highest above sea level, Mount Everest. The Himalayas have profoundly shaped the cultures of South Asia. Many Himalayan peaks are sacred in both Buddhism and Hinduism.


By Sudan Shrestha. License: CC-by-sa 3.0

Edward, the headmaster of Marjar University, is doing a research about the Himalayas. To simplify the model, Edward thinks that there are N mountains in the Himalayas and they are lined up. Edward numbered them from 1 to N from left to right. What's more, Edward defines peaks of the Himalayas which satisfy:

  1. 1 < i < N
  2. Hi - 1 < Hi > Hi + 1, where Hi means the height of the i-th mountain

Then the i-th mountain is called a peak.

Furthermore, Edward found an interesting fact about the Himalayas from its history: earthquakes will change the height of some continuous mountains. To be more specific, for an earthquake, we record it as (L, R, A, B), which means the height of the i-th (L ≤ i ≤ R) mountain will change by A + (i - L) * B after the earthquake.

Edward wants to know the amount of peaks after each earthquake. Please tell him.

Input

There are multiple test cases. The first line of input contains an integer T (≤ 10) indicating the number of test case. For each test case:

The first line contains two integers N, M (1 ≤ N, M ≤ 105) indicating the number of the mountains and the number of the earthquakes.

The next line contains N (1 ≤ N ≤ 105) integers, the i-th integer is the initial height Hi of the i-th mountain (0 ≤ Hi ≤ 105).

Then followed by M lines, each line contains four integers L, R, A, B (1 ≤ L ≤ R ≤ N, 1 ≤ B ≤ 105, -105 ≤ A ≤ 105) of an earthquake, in chronological order.

Output

For each earthquake, output the amount of peak after it.

Sample Input

2
4 2
1 5 3 0
3 4 1 1
3 4 2 1
4 2
1 5 3 0
3 4 1 1
3 4 1 1

Sample Output

1
1
1
0

Hint

1 5 3 0 -> 1 5 4 2 -> 1 5 6 5

H. HIMALAYAS

考虑相邻两个数的大小关系只有三种情况,并且每次修改操作的bb都是大于0的,那么除了端点部分,大小关系一定会从> \to = \to <>=<。总的变化次数一定是O(n+m)O(n+m)的。于是每次的修改操作,只要暴力找出这些改变的位置,计算下这些位置对答案的影响就好了。

d_i=h_i-h_{i-1}di=hihi1,用一棵线段树维护d_i < 0di<0(对应了 > 关系)的位置,用一个set之类的维护d_i=0di=0的位置,d_i > 0di>0的位置不需要维护。那么每次修改操作只有那些d_i + b >= 0di+b>=0d_i=0di=0并且在区间内的位置以及区间端点会对答案有影响。前者用线段树维护最值(这个线段树大概还需要支持单点修改,区间加一个数等等操作)即可,后者直接在set上lower_bound即可。找出这些位置之后,随便统计一些就好了。

#include 
using namespace std;
typedef long long LL;

class Solution {
  static const int MAXN = 100000 + 10;
  static const LL inf = 1ll << 60;
  int a[MAXN], n, q, ret;
  bool mark[MAXN];
  set eq;

  struct BIT {
    LL u[MAXN];
    int n;
    void clr(int _n) {
      n = _n;
      memset(u, 0, sizeof(u[0]) * (n + 1));
    }
    void add(int x, LL v) {
      for (; x <= n; x += ~x & x + 1) u[x] += v;
    }
    void add(int l, int r, LL v) {//[l, r]
      add(l, v); add(r + 1, -v);
    }
    LL get(int x, LL r = 0) {//[0,x]
      for (; x >= 0; x -= ~x & x + 1) r += u[x];
      return r;
    }
  } bit;

  struct SegTree {
    #define lson (rt<<1)
    #define rson (rt<<1|1)
    #define mid ((l+r)>>1)
    struct Node {
      LL val, add;
      int idx;
      void mark(LL v) {
        val += v; add += v;
      }
    } T[MAXN << 2];
    void upd(int rt) {
      T[rt].val = max(T[lson].val, T[rson].val);
      if (T[rt].val == T[lson].val) T[rt].idx = T[lson].idx;
      else T[rt].idx = T[rson].idx;
    }
    void psd(int rt) {
      T[lson].mark(T[rt].add);
      T[rson].mark(T[rt].add);
      T[rt].add = 0;
    }
    void build(int rt, int l, int r) {
      T[rt].add = 0; T[rt].val = -inf; T[rt].idx = l;
      if (l + 1 == r) return;
      build(lson, l, mid);
      build(rson, mid, r);
    }
    void ins(int rt, int l, int r, int x, LL v) {
      if (l + 1 == r) {T[rt].val = v; return;}
      psd(rt);
      if (x < mid) ins(lson, l, mid, x, v);
      else ins(rson, mid, r, x, v);
      upd(rt);
    }
    void add(int rt, int l, int r, int L, int R, LL v) {
      if (L <= l && R >= r) {T[rt].mark(v); return;}
      psd(rt);
      if (L < mid) add(lson, l, mid, L, R, v);
      if (R > mid) add(rson, mid, r, L, R, v);
      upd(rt);
    }
    const Node& Max() const {return T[1];}
  } st;

public:
  void run() {
    scanf("%d%d", &n, &q); ret = 0;
    for (int i = 0; i < n; ++i) scanf("%d", a + i);
    st.build(1, 0, n); bit.clr(n);
    eq.clear(); a[n] = 0;
    memset(mark, 0, sizeof(mark));
    for (int i = n - 1; i > 0; --i) {
      a[i] -= a[i - 1];
      if (a[i] == 0) eq.insert(i);
      if (a[i] < 0) st.ins(1, 0, n, i, a[i]);
      if (a[i] > 0 && a[i + 1] < 0) ++ret;
      bit.add(i, i, a[i]);
    }
    cerr << ret << std::endl;
    for (int i = 0; i < q; ++i) {
      int l, r, a, b; scanf("%d%d%d%d", &l, &r, &a, &b);
      LL cl = a, cr = a + 1ll * b * (r - l); --l;
      vector pt;
      st.ins(1, 0, n, l, -inf); eq.erase(l);
      if (l) pt.push_back(l);
      if (l < r - 1) {
        for (auto it = eq.lower_bound(l); it != eq.end(); it = eq.erase(it)) {
          if (*it >= r) break; pt.push_back(*it);
        }
        st.add(1, 0, n, l + 1, r, b);
        while (st.Max().val >= 0) {
          pt.push_back(st.Max().idx);
          st.ins(1, 0, n, pt.back(), -inf);
        }
      }
      if (r < n) {
        st.ins(1, 0, n, r, -inf);
        eq.erase(r);
        pt.push_back(r);
      }
      for (auto &x: pt) mark[x] = true;
      for (auto &x: pt) {
        LL v = bit.get(x);
        if (x > 1 && v < 0 && bit.get(x - 1) > 0) --ret;
        if (x + 1 < n && v > 0 && bit.get(x + 1) < 0 && !mark[x + 1]) --ret;
      }
      if (l) bit.add(l, l, cl);
      if (l < r - 1) bit.add(l + 1, r - 1, b);
      if (r < n) bit.add(r, r, -cr);
      for (auto &x: pt) {
        LL v = bit.get(x);
        if (x > 1 && v < 0 && bit.get(x - 1) > 0) ++ret;
        if (x + 1 < n && v > 0 && bit.get(x + 1) < 0 && !mark[x + 1]) ++ret;
        if (v == 0) eq.insert(x);
        if (v < 0) st.ins(1, 0, n, x, v);
      }
      for (auto &x: pt) mark[x] = false;
      printf("%d\n", ret);
    }
  }
} sol;

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) sol.run();
  return 0;
}


People Counting

Time Limit: 2 Seconds       Memory Limit: 65536 KB

In a BG (dinner gathering) for ZJU ICPC team, the coaches wanted to count the number of people present at the BG. They did that by having the waitress take a photo for them. Everyone was in the photo and no one was completely blocked. Each person in the photo has the same posture. After some preprocessing, the photo was converted into a H×Wcharacter matrix, with the background represented by ".". Thus a person in this photo is represented by the diagram in the following three lines:

.O.
/|\
(.)

Given the character matrix, the coaches want you to count the number of people in the photo. Note that if someone is partly blocked in the photo, only part of the above diagram will be presented in the character matrix.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first contains two integers H, W (1 ≤ H, W ≤ 100) - as described above, followed by H lines, showing the matrix representation of the photo.

Output

For each test case, there should be a single line, containing an integer indicating the number of people from the photo.

Sample Input

2
3 3
.O.
/|\
(.)
3 4
OOO(
/|\\
()))

Sample Output

1
4

I. PEOPLE COUNTING

拿那个人的形状去匹配每一个位置就好了,注意可以人跑到照片外面去,似乎样例就有这种case。

#include 
using namespace std;
const int MAXN = 200;
char s[MAXN][MAXN];

int main() {
  int T; scanf("%d", &T);
  for (int cas = 1; cas <= T; ++cas) {
    int n, m; scanf("%d%d", &n, &m);
    memset(s, 0, sizeof(s));
    for (int i = 0; i < n; ++i) scanf("%s", s[i + 10] + 10);
    int ret = 0;
    for (int i = 0; i < n + 10; ++i) {
      for (int j = 0; j < m + 10; ++j) {
        ret += s[i][j + 1] == 'O' || s[i + 1][j] == '/' || s[i + 1][j + 1] == '|' ||
          s[i + 1][j + 2] == '\\' || s[i + 2][j] == '(' || s[i + 2][j + 2] == ')';
      }
    }
    cout << ret << endl;
  }
  return 0;
}


Rush on the Cube

Time Limit: 2 Seconds       Memory Limit: 65536 KB       Special Judge

Carl the ant is our old friend. In 2004, he was a little mixed-up and always taking strange paths, and in 2009, he had straightened his life and started to take the shortest path between any pair of points. But now, he travels to a novel place, and it's not easy for him to choose the shortest path. Can you help him?

The place is considered as an infinite three-dimensional space divided into grids. Some of them are black and the others are white. The black girds represent the land of the world and the white grids represent the air.

Obviously, Carl can only walk on the surface (including edge or vertex) of black grids. Luckily, the grids are regular. Every black grid shares common vertex with exact 8 other black grids and has no common edges or faces with these black grids. The following picture shows a fraction of the grid world:

Now, we place the center of one black grid on the origin and the edge of the grids are paralleled with axes. Also, we assume that every edge is exactly 1cm long. Carl has told you his starting point and the destination point, help him to calculate the distance of the shortest path between them.

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases. For each test case:

The only line contains 6 numbers X1, Y1, Z1, X2, Y2 and Z2 (-104 ≤ X1, Y1, Z1, X2, Y2, Z2 ≤ 104), representing the coordinates of the starting point and the destination point. It is guaranteed that both points are on the surface of black grid.

Output

For each case, output the length in centimeters of the shortest path from the starting point to the destination point. Absolute error or relative error less than 10-8 will be accepted.

Sample Input

3
0.5 0.5 0.5 0.5 -0.5 -0.5
-0.5 -0.5 -0.5 1.5 1.5 1.5
0.4 0.3 0.5 0.6 0.5 0.7

Sample Output

1.4142135623730950488016887242097
4.4721359549995793928183473374626
0.4472135954999579392818347337462

Hint

For the first sample, the starting point and the destination point are on the same surface so just go straight there.

For the second sample, Carl can go to (0.5, 0.5, 0.5) first and then go to the destination point.

For the third sample, Carl can also go to (0.5, 0.5, 0.5) first and then go to the destination point.

J. RUSH ON THE CUBE

这题有毒。分为两种情况,起点终点是否在同一个立方体内处理。在同一个立方体内的时候,分三种情况讨论,或者直接模拟退火求最短在不同立方体内时,一定是分别走到顶点然后再走。枚举走到哪个顶点,一共64种情况。顶点间走的时候,可以A*或者模拟退火求最短路,或者贪心,面对角线优先,然后体对角线,然后边,有些要讨论的细节,可以暴力枚举走到附近点,然后贪心。

#include

using namespace std;

struct Pt{
	double x, y, z;
} A,B,C,D;

const double eps = 1e-8;
const double _5 = sqrt(5.0);
const double _2 = sqrt(2.0);
double f[3];

typedef pair PPP;

struct Pi{
	int x, y, z;
};

bool operator < (const Pi & a, const Pi & b){
	return (a.x < b.x);
}

bool operator == (const Pi & a, const Pi & b){
	return (a.x == b.x && a.y == b.y && a.z == b.z);
}

void Pit(const Pt & X){
	cout<> 1) & 1), X.z - 0.5 + ((k >> 2) & 1)};
}

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

#ifdef SPFA
	#define MAXD 60
#else
	#define MAXD 30
#endif

bool dis2_inRange(int x, int y, int z){
	return 0 <= x && x <= MAXD && 0 <= y && y <= MAXD && 0 <= z && z <= MAXD;
}

inline double dis2_getDis(int cnt){
	return cnt > 3 ? 1E100 : cnt == 3 ? _5 : cnt == 2 ? _2 : 1.0;
}

int dis2_getDis(int x, int y, int z, int ux, int uy, int uz){
	const int t = -2;
	if (((x | 1) != (ux | 1) || (y | 1) != (uy | 1) || (z | 1) != (uz | 1))
		&& ((x + (x & 1)) != (ux + (ux & 1)) || (y + (y & 1)) != (uy + (uy & 1)) || (z + (z & 1)) != (uz + (uz & 1))))
		return 4;
	return (x != ux) + (y != uy) + (z != uz);
}

void dis2_pre(Pi st, double (&dis)[MAXD + 1][MAXD + 1][MAXD + 1], int (&dt)[MAXD + 1][MAXD + 1][MAXD + 1][3]){
	static bool in[MAXD + 1][MAXD + 1][MAXD + 1];
	for (int i = 0; i <= MAXD; ++i)
		for (int j = 0; j <= MAXD; ++j)
			for (int k = 0; k <= MAXD; ++k){
				dis[i][j][k] = 1E100;
				in[i][j][k] = false;
				dt[i][j][k][0] = dt[i][j][k][1] = dt[i][j][k][2] = 0;
			}
	dis[st.x][st.y][st.z] = 0;
	queue Q;
	Q.push(st);
	while (!Q.empty()){
		Pi u = Q.front();
		Q.pop();
//		fprintf(stderr, "start update: %d %d %d\n", u.x, u.y, u.z);
		for (int i = -1; i <= 1; ++i)
			for (int j = -1; j <= 1; ++j)
				for (int k = -1; k <= 1; ++k){
					int x = u.x + i, y = u.y + j, z = u.z + k;
					if (dis2_inRange(x, y, z)){
						int tmp = dis2_getDis(u.x, u.y, u.z, x, y, z);
						if (dis[x][y][z] > dis[u.x][u.y][u.z] + dis2_getDis(tmp)){
							dis[x][y][z] = dis[u.x][u.y][u.z] + dis2_getDis(tmp);
							dt[x][y][z][0] = dt[u.x][u.y][u.z][0];
							dt[x][y][z][1] = dt[u.x][u.y][u.z][1];
							dt[x][y][z][2] = dt[u.x][u.y][u.z][2];
							++dt[x][y][z][tmp - 1];
//							printf("%d %d %d\n", x, y, z);
							if (!in[x][y][z]){
//								puts("- =");
								in[x][y][z] = true;
								Q.push((Pi){x, y, z});
							}
						}
					}
				}
		in[u.x][u.y][u.z] = false;
	}
}

double dis2(Pi st, Pi ed){
	static bool used = false;
	static double dis[8][MAXD + 1][MAXD + 1][MAXD + 1];
	static int dt[8][MAXD + 1][MAXD + 1][MAXD + 1][3];

	/* prework */
	if (!used){
		used = true;
		for (int i = 0; i < 8; ++i)
			dis2_pre((Pi){i >> 2 & 1, i >> 1 & 1, i & 1}, dis[i], dt[i]);
	}

	int dx = ed.x - st.x, dy = ed.y - st.y, dz = ed.z - st.z;

	if (dx < dy){
		swap(dx, dy);
		swap(st.x, st.y);
		swap(ed.x, ed.y);
	}
	if (dx < dz){
		swap(dx, dz);
		swap(st.x, st.z);
		swap(ed.x, ed.z);
	}
	if (dy < dz){
		swap(dy, dz);
		swap(st.y, st.z);
		swap(ed.y, ed.z);
	}

	int cnt2 = 0, cnt1 = 0;
#ifndef SPFA
	int Maki = 5;
	int tx = max(0, dx - Maki) & -4, ty = max(0, dy - Maki) & -4, tz = max(0, dz - Maki) & -4;
//	printf("%d %d %d\n", tx, ty, tz);
	dx -= tx, dy -= ty, dz -= tz;
	if (ty + tz <= tx){
		tx -= cnt2 = ty + tz;
		cnt1 += max(0, tx - dy - dz);
		dx += min(dy + dz, tx);
	}
	else
		cnt2 += tx + ty + tz >> 1;
//	printf("- %d %d %d, %d %d\n", dx, dy, dz, cnt1, cnt2);
//	printf("st: %d %d %d\n", st.x, st.y, st.z);
#endif
	ed.x = st.x + dx;
	ed.y = st.y + dy;
	ed.z = st.z + dz;
	int type = st.x << 2 | st.y << 1 | st.z;
//	printf("%d %d %d\n", cnt1 + dt[type][ed.x][ed.y][ed.z][0], cnt2 + dt[type][ed.x][ed.y][ed.z][1], dt[type][ed.x][ed.y][ed.z][2]);
	return cnt1 + cnt2 * _2 + dis[type][ed.x][ed.y][ed.z];
}

#undef MAXD

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

double _dis2(Pt P, Pt Q){
	f[0] = fabs(P.x - Q.x);
	f[1] = fabs(P.y - Q.y);
	f[2] = fabs(P.z - Q.z);
	sort(f, f + 3);
	f[2] -= f[1];
	f[1] -= f[0];
	return _5 * f[0] + _2 * f[1] + f[2];
}

Pt operator -(const Pt & a, const Pt & b){
	return (Pt){a.x - b.x, a.y - b.y, a.z - b.z};
}

Pt operator +(const Pt & a, const Pt & b){
	return (Pt){a.x + b.x, a.y + b.y, a.z + b.z};
}

Pt operator *(const Pt & a, double x){
	return (Pt){a.x * x, a.y * x, a.z * x};
}

double sqr(double x){
	return x * x;
}

inline double len(const Pt & a){
	return sqrt(sqr(a.x)+sqr(a.y)+sqr(a.z));
}

double dg(double x, double y){
	return sqrt(sqr(x) + sqr(y));
}

PPP a[100];

int like(double p, double q, double r){
	if (fabs(p - q) < eps && fabs(q - r) < eps)
		return 1;
	else
		return 0;
}

double le[100][100];

double Get_s(Pt p, Pt q){
	for(int i = 0; i < 12; i++)
		for(int j = 0; j < 12; j++){
			if (like(a[i].first.x, a[j].first.x, 0) || like(a[i].first.x, a[j].first.x, 1))
				le[i][j] = len(a[i].first - a[j].first);
			else if (like(a[i].first.y, a[j].first.y, 0) || like(a[i].first.y, a[j].first.y, 1))
				le[i][j] = len(a[i].first - a[j].first);
			else if (like(a[i].first.z, a[j].first.z, 0) || like(a[i].first.z, a[j].first.z, 1))
				le[i][j] = len(a[i].first - a[j].first);
			else
				le[i][j] = 12345678;
		}
	for(int i = 0; i < 12; i++){
		if (like(a[i].first.x, p.x, 0) ||like(a[i].first.x, p.x, 1) ||
			like(a[i].first.y, p.y, 0) ||like(a[i].first.y, p.y, 1) ||
			like(a[i].first.z, p.z, 0) ||like(a[i].first.z, p.z, 1))
			le[i][13] = le[13][i] = len(p - a[i].first);
		else
			le[i][13] = le[13][i] = 12345678;
		if (like(a[i].first.x, q.x, 0) ||like(a[i].first.x, q.x, 1) ||
			like(a[i].first.y, q.y, 0) ||like(a[i].first.y, q.y, 1) ||
			like(a[i].first.z, q.z, 0) ||like(a[i].first.z, q.z, 1))
			le[i][12] = le[12][i] = len(q - a[i].first);
		else
			le[i][12] = le[12][i] = 12345678;
	}
	le[13][13] = le[12][12] = 0;
	if (like(p.x, q.x, 0) || like(p.y, q.y, 0) || like(p.z, q.z, 0) || like(p.x, q.x, 1) || like(p.y, q.y, 1) || like(p.z, q.z, 1))
		le[13][12] = le[12][13] = len(p - q);
	else
		le[13][12] = le[12][13] = 12345678;
	for(int k = 0; k < 14; k++)
		for(int i = 0; i < 14; i++)
			for(int j = 0; j < 14; j++)
				le[i][j] = min(le[i][j] , le[i][k] + le[k][j]);
	return le[12][13];
}

double tf(Pt p, Pt q){
	for(int i = 0; i <= 1; i++)
		for(int j = 0; j <= 1; j++)
			a[(i << 1) + j + 0] = (PPP){(Pt){i, j, rand()/(double)(RAND_MAX)}, (Pt){0, 0, 1}};
	for(int i = 0; i <= 1; i++)
		for(int j = 0; j <= 1; j++)
			a[(i << 1) + j + 4] = (PPP){(Pt){i, rand()/(double)(RAND_MAX), j}, (Pt){0, 1, 0}};
	for(int i = 0; i <= 1; i++)
		for(int j = 0; j <= 1; j++)
			a[(i << 1) + j + 8] = (PPP){(Pt){rand()/(double)(RAND_MAX), i, j}, (Pt){1, 0, 0}};
	double now = Get_s(p, q);
	double t = 0.5;
	while(t > 0.001){
		int flag = 0;
		for(int i = 0; i < 12; i++)
			if (!flag){
				a[20] = a[i];
				a[i].first = a[i].first + (a[i].second * t);
				double tmp = Get_s(p, q);
				if (tmp < now){
					flag = 1;
					while(tmp < now){
						now = tmp;
						a[20] = a[i];
						a[i].first = a[i].first + (a[i].second * t);
						tmp = Get_s(p, q);
					}
				}
				a[i] = a[20];
			}
		t *= 0.9;
	}
	return now;
}

double dis1(Pt P, Pt Q, Pt R){
//	puts("QAQ");
	P = P - R;
	Q = Q - R;
	P.x += 0.5, P.y += 0.5, P.z += 0.5;
	Q.x += 0.5, Q.y += 0.5, Q.z += 0.5;
//	Pit(P), Pit(Q);
	double ans = 10;
	for(int ts = 0; ts < 100; ts++){
//		puts("= -");
		ans = min(ans, tf(P, Q));
	}
//	cout<<"tf:\t"< eps){
		if (fabs(fabs(P.y) - 0.5) <= eps){
			swap(P.y, P.x);
			swap(Q.y, Q.x);
		}
		else{
			swap(P.z, P.x);
			swap(Q.z, Q.x);
		}
	}
	if (fabs(P.x + 0.5) < eps){
		P.x = -P.x, Q.x = -Q.x;
	}
	if (fabs(Q.x - 0.5) < eps){//On the same face
	//	cout<<"tl:\t"< eps){
			swap(Q.y, Q.z);
			swap(P.y, P.z);
		}
		if (fabs(Q.y + 0.5) < eps){
			Q.y = -Q.y, P.y = -P.y;
		}
	//	cout<<"tl:\t"< eps){
		if ((y & 1) != (x & 1)){
			y = (int)(round(X.y * 2 - y));
		}
		if ((z & 1) != (x & 1)){
			z = (int)(round(X.z * 2 - z));
		}
	}
	else{
		if (fabs(fabs(fmod(X.y, 1)) - 0.5) > eps){
			if ((y & 1) != (x & 1)){
				x = (int)(round(X.x * 2 - x));
			}
			if ((z & 1) != (y & 1)){
				z = (int)(round(X.z * 2 - z));
			}
		}
		else{
			if ((z & 1) != (x & 1)){
				x = (int)(round(X.x * 2 - x));
			}
			if ((z & 1) != (y & 1)){
				y = (int)(round(X.y * 2 - y));
			}
		}
	}
	return (Pt){(double)x, (double)y, (double)z};
}

double Nico(Pt P, Pt Q){
	Pi p = (Pi){(int)(round(P.x + 0.5)), (int)(round(P.y + 0.5)), (int)(round(P.z + 0.5))};
	Pi q = (Pi){(int)(round(Q.x + 0.5)), (int)(round(Q.y + 0.5)), (int)(round(Q.z + 0.5))};
	q.x -= (p.x / 2) * 2, p.x -= (p.x / 2) * 2;
	if (p.x == -1){q.x += 2, p.x += 2;}
	q.y -= (p.y / 2) * 2, p.y -= (p.y / 2) * 2;
	if (p.y == -1){q.y += 2, p.y += 2;}
	q.z -= (p.z / 2) * 2, p.z -= (p.z / 2) * 2;
	if (p.z == -1){q.z += 2, p.z += 2;}
	if (q.x <= 0){
		q.x = 1 - q.x;
		p.x = 1 - p.x;
	}
	if (q.y <= 0){
		q.y = 1 - q.y;
		p.y = 1 - p.y;
	}
	if (q.z <= 0){
		q.z = 1 - q.z;
		p.z = 1 - p.z;
	}
	return dis2(p, q);
}

void ck(double x){
	assert(x >= -9999  && x <= 9999);
}

int main(){
//	freopen("J.in", "r", stdin);
//	freopen("J.out", "w", stdout);
//

	srand(time(NULL));
	int T;
	scanf("%d",&T);

/*
	for(int i = 0; i < 100;  i++){
		scanf("%lf%lf%lf", &A.x, &A.y, &A.z);
		scanf("%lf%lf%lf", &B.x, &B.y, &B.z);
		dis1(A, B, (Pt){0, 0, 0});
		_dis1(A, B, (Pt){0, 0, 0});
	}
	return 0;
*/
	while(T--){
		scanf("%lf%lf%lf", &A.x, &A.y, &A.z);
		scanf("%lf%lf%lf", &B.x, &B.y, &B.z);
		ck(A.x); ck(A.y); ck(A.z);
		ck(B.x); ck(B.y); ck(B.z);
		C = getcenter(A);
		assert((A.x - C.x - eps) <= 0.5 && (A.x - C.x + eps) >= -0.5);
		assert((A.y - C.y - eps) <= 0.5 && (A.y - C.y + eps) >= -0.5);
		assert((A.z - C.z - eps) <= 0.5 && (A.z - C.z + eps) >= -0.5);
		assert(((int)round(C.x - C.y)) % 2 == 0);
		assert(((int)round(C.x - C.z)) % 2 == 0);
		D = getcenter(B);
		assert((B.x - D.x - eps) <= 0.5 && (B.x - D.x + eps) >= -0.5);
		assert((B.y - D.y - eps) <= 0.5 && (B.y - D.y + eps) >= -0.5);
		assert((B.z - D.z - eps) <= 0.5 && (B.z - D.z + eps) >= -0.5);
		assert(((int)round(D.x - D.y)) % 2 == 0);
		assert(((int)round(D.x - D.z)) % 2 == 0);
		double ans = 1234567;
		if (C == D){
			ans = _dis1(A, B, C);
		}
		else{
			
			for(int i = 0; i < 8; i++)
				for(int j = 0; j < 8; j++){
				//	ans = min(ans,dis2(work(C, i), work(D, j)));
				//	dis1(A, work(C, i), C);
				//	_dis1(A, work(C, i), C);
				//	dis1(B, work(D, j), D);
				//	_dis1(B, work(D, j), D);
					ans = min(ans, _dis1(A, work(C, i), C) + _dis1(B, work(D, j), D) + Nico(work(C, i), work(D, j)));
				//	ans = min(ans, dis1(A, work(C, i), C) + dis1(B, work(D, j), D) + dis2(work(C, i), work(D, j)));
				}
		}
		printf("%.16f\n", ans);
	}
	return 0;
}
 

/*
0.733017 0.493771 1
0.429134 0 0.88777
tf:	0.678462
tl:	0.677924
0.25458 0 1
0.165501 1 0.459615
tf:	1.4132
tl:	1.4108
0.561626 0 0
1 0.0775424 0.207269
tf:	0.556202
tl:	0.555994
0 0.98381 1
1 0.962809 0.831134
tf:	1.06045
tl:	1.05357
*/


Highway Project

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Edward, the emperor of the Marjar Empire, wants to build some bidirectional highways so that he can reach other cities from the capital as fast as possible. Thus, he proposed the highway project.

The Marjar Empire has N cities (including the capital), indexed from 0 to N - 1 (the capital is 0) and there are M highways can be built. Building the i-th highway costs Ci dollars. It takes Di minutes to travel between city Xi and Yi on the i-th highway.

Edward wants to find a construction plan with minimal total time needed to reach other cities from the capital, i.e. the sum of minimal time needed to travel from the capital to city i (1 ≤ i ≤ N). Among all feasible plans, Edward wants to select the plan with minimal cost. Please help him to finish this task.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first contains two integers N, M (1 ≤ N, M ≤ 105).

Then followed by M lines, each line contains four integers Xi, Yi, Di, Ci (0 ≤ Xi, Yi < N, 0 < Di, Ci < 105).

Output

For each test case, output two integers indicating the minimal total time and the minimal cost for the highway project when the total time is minimized.

Sample Input

2
4 5
0 3 1 1
0 1 1 1
0 2 10 10
2 1 1 1
2 3 1 2
4 5
0 3 1 1
0 1 1 1
0 2 10 10
2 1 2 1
2 3 1 2

Sample Output

4 3
4 4


K. HIGHWAY PROJECT

先求出最短路图,就是那些dis_u+w(u,v)=dis_vdisu+w(u,v)=disv的边(u,v)(u,v)都拿出来,剩下来就是给出一个有向无环图,要求找个最小树形图,你可以选择套O((n+m)\log n)O((n+m)logn)的模板,也可以直接贪心,对于每个点选代价最小的入边。

#include 
using namespace std;
typedef long long LL;
typedef pair PII;

const int MAXN = 100000 + 10;
vector G[MAXN];
int X[MAXN], Y[MAXN], D[MAXN], C[MAXN];
LL ds[MAXN], ms[MAXN];
int n, m;

void run() {
  cin >> n >> m;
  for (int i = 0; i < n; ++i) {
    G[i].clear();
    ms[i] = ds[i] = 1ll << 60;
  }
  for (int i = 0; i < m; ++i) {
    cin >> X[i] >> Y[i] >> D[i] >> C[i];
    G[X[i]].push_back(PII(Y[i], i));
    G[Y[i]].push_back(PII(X[i], i));
  }
  ds[0] = ms[0] = 0;
  queue Q; Q.push(0);
  vector vs(n);
  while (!Q.empty()) {
    int u = Q.front(); Q.pop(); vs[u] = 0;
    for (auto &x: G[u]) {
      int v = x.first, w = D[x.second];
      if (ds[v] > ds[u] + w) {
        ds[v] = ds[u] + w;
        if (!vs[v]) vs[v] = 1, Q.push(v);
      }
    }
  }
  for (int i = 0; i < m; ++i) {
    if (ds[X[i]] + D[i] == ds[Y[i]]) {
      ms[Y[i]] = min(ms[Y[i]], (LL)C[i]);
    }
    if (ds[Y[i]] + D[i] == ds[X[i]]) {
      ms[X[i]] = min(ms[X[i]], (LL)C[i]);
    }
  }
  LL SD = 0, SC = 0;
  for (int i = 0; i < n; ++i) SD += ds[i], SC += ms[i];
  cout << SD << " " << SC << endl;
}

int main() {
  int T; cin >> T;
  for (int cas = 1; cas <= T; ++cas) run();
  return 0;
}


Very Happy Great BG

Time Limit: 2 Seconds       Memory Limit: 65536 KB

The summer training of ZJU ICPC in July is about to end. To celebrate this great and happy day, the coach of ZJU ICPC Team decided to BG everyone!

After a brief discussion, they decided to go to Lou Wai Lou to have a great dinner. Each team member can bring some friends with him/her. Of course, they need to tell the coach the number of friends they will bring.

Now the coach wants to know the total number of participants (excluding the coach himself). Please tell him.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains an integer N (1 <= N <= 40) - the number of ZJU ICPC members.

The second line contains N non-negative integers, the i-th integer indicates the number of friends (< 1000) that the i-th team member will bring.

Output

For each test case, output the total number of participants.

Sample Input

4
5
0 0 1 2 3
1
0
10
1 2 3 4 5 6 7 8 9 10
2
5 3

Sample Output

11
1
65
10

L. VERY HAPPY GREAT BG

对输入的数求个和,包括nn

#include 
using namespace std;

int main() {
  int T; cin >> T;
  for (int cas = 1; cas <= T; ++cas) {
    int n; cin >> n;
    for (int i = n; i >= 1; --i) {
      int x; cin >> x; n += x;
    }
    cout << n << endl;
  }
  return 0;
}




你可能感兴趣的:(比赛经验)