C. Sum of Suffix Sums (后缀和/思维)

时间复杂度 :$O(q)$

题意

    起始有一个空的数组,现在对该数组进行$q$ 次操作:

  • 给定两个非负整数 $t$ 和 $v$ ,从末尾移除 $t$ 个元素并将元素 $v$ 加到末尾。保证每次元素数量不小于 $t$

    每次操作后输出每个索引的后缀和总和,由于答案可能会很大,对答案进行 $1000000007$ 取模.

数据范围

  • $1 \le q \le 5 \times 10^5$
  • $0 \le v \le 10^9$

思路

    由于每次操作输出后缀总和,不妨直接从答案出发;设 $sum[i]$ 为前 $i$ 个元素的后缀总和,当末尾添加一个元素( 第 $i+1 $ 个元素 )$ v$ 时,其对后缀的贡献为 $v \times i$ ,即$sum[i+1]=sum[i]+v*i$ ; 当取出 $t$ 个元素时,类似于栈的 $pop$ 操作,直接将元素数量减去 $t$ 即可 .

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<bits/stdc++.h>
#define endl '\n'
using i64 = long long;
using namespace std;
const i64 p = 1e9 + 7;
signed main(){
std::ios::sync_with_stdio(false);cin.tie(0);
int q, top = 0;
cin >> q;
vector<i64> sum(q + 5);
for (int i = 1; i <= q;i++){
int t, v;
cin >> t >> v;
top -= t;
top++;
sum[top] = (sum[top - 1] % p + (top * v) % p) % p;
cout << sum[top] << endl;
}
return 0;
}

H. World Finals (模拟)

时间复杂度:$O(Max(m,n \log n))$

题意

    共有两场比赛可供队伍参加,分别给定 $n$ 和 $m$ ,表示两场比赛可能参赛的队伍数量,每支队伍有对应的答题数 $p$ 和罚时 $t$ (按照 $icpc$ 赛制进行排序),保证不会出现答题数和罚时完全相同的队伍。可能出现一支队伍有两场比赛的参与权,但每支队伍只能参加一场比赛,其中队伍名 $lzr010506$ 有两场的参赛可能。求队伍 $lzr010506$ 可能取得的最高排名 .

数据范围

  • $1 \le n,m \le 10^5$
  • $1 \le p,t \le 10^9$

思路

​    简单模拟题,要使得指定队伍排名最高,则其余拥有两场比赛参赛权的队伍应当去参加另一场比赛.

​    对所有队伍根据规则进行结构体排序,再记录拥有两场比赛参赛权的队伍,依次枚举其在各自比赛的位次,当遇到特殊队伍则跳过,两种比赛的最高排名取最大值即可.

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
#define endl '\n'
using i64 = long long;
using namespace std;
struct node{
string name;
int p, t;
bool operator<(const node x)const{
if(p!=x.p)
return p > x.p;
else
return t < x.t;
}
} team1[100010], team2[100010];
signed main(){
std::ios::sync_with_stdio(false);cin.tie(0);
int n, m;
map<string, int> cnt;
cin >> n;
for (int i = 1; i <= n;i++){
cin >> team1[i].name >> team1[i].p >> team1[i].t;
cnt[team1[i].name]++;
}
sort(team1 + 1, team1 + n + 1);
cin >> m;
for (int i = 1; i <= m; i++){
cin >> team2[i].name >> team2[i].p >> team2[i].t;
cnt[team2[i].name]++;
}
sort(team2 + 1, team2 + m + 1);
int ans = 1e6;
int tot = 0;
for (int i = 1; i <= n;i++){
if(team1[i].name=="lzr010506"){
tot++;
break;
}
if(cnt[team1[i].name]==2)
continue;
else
tot++;
}
ans = min(ans, tot);
tot = 0;
for (int i = 1; i <= m; i++){
if (team2[i].name == "lzr010506"){
tot++;
break;
}
if (cnt[team2[i].name] == 2)
continue;
else
tot++;
}
ans = min(ans, tot);
cout << ans << endl;
/*for (int i = 1; i <= n;i++)
cout << team1[i].name << ' ' << team1[i].p << ' ' << team1[i].t << endl;
for (int i = 1; i <= m; i++)
cout << team2[i].name << ' ' << team2[i].p << ' ' << team2[i].t << endl;*/
return 0;
}