题解

A Grass Field

题面翻译

给出一个 2×22 \times 22×2 的矩阵,矩阵的值都是 000 和 111,定义一次操作:选择一个点,将其所在的行和列的点的值全部修改为 000,求最少几次操作将整个矩阵修改为 000。

by @Leonador

题目描述

There is a field of size 2×22 \times 22×2 . Each cell of this field can either contain grass or be empty. The value ai,ja_{i, j}ai,j​ is 111 if the cell (i,j)(i, j)(i,j) contains grass, or 000 otherwise.

In one move, you can choose one row and one column and cut all the grass in this row and this column. In other words, you choose the row xxx and the column yyy , then you cut the grass in all cells ax,ia_{x, i}ax,i​ and all cells ai,ya_{i, y}ai,y​ for all iii from 111 to 222 . After you cut the grass from a cell, it becomes empty (i. e. its value is replaced by 000 ).

Your task is to find the minimum number of moves required to cut the grass in all non-empty cells of the field (i. e. make all ai,ja_{i, j}ai,j​ zeros).

You have to answer ttt independent test cases.

输入格式

The first line of the input contains one integer ttt ( 1≤t≤161 \le t \le 161≤t≤16 ) — the number of test cases. Then ttt test cases follow.

The test case consists of two lines, each of these lines contains two integers. The $ j $ -th integer in the $ i $ -th row is ai,ja_{i, j}ai,j​ . If ai,j=0a_{i, j} = 0ai,j​=0 then the cell (i,j)(i, j)(i,j) is empty, and if ai,j=1a_{i, j} = 1ai,j​=1 the cell (i,j)(i, j)(i,j) contains grass.

输出格式

For each test case, print one integer — the minimum number of moves required to cut the grass in all non-empty cells of the field (i. e. make all ai,ja_{i, j}ai,j​ zeros) in the corresponding test case.

样例 #1

样例输入 #1

3
0 0
0 0
1 0
0 1
1 1
1 1

样例输出 #1

0
1
2

解析

选择一行和一列,那么最多可以一次删除3个数,所以只需要1判断四个数的和就行了。000输出000,444输出222,其余都是111。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5;
int n, m;
int a[N][N];
void solve()
{int cnt = 0;for(int i = 1; i <= 2; i ++){for(int j = 1; j <= 2; j ++){scanf("%d", &a[i][j]);if(a[i][j] == 1){cnt ++;}}}if(cnt == 4){printf("2\n");}else if(cnt < 4 && cnt > 0){printf("1\n");}else printf("0\n");
}
int main()
{int t;cin >> t;while(t --){solve();}
}

B Permutation

题目描述

Recall that a permutation of length nnn is an array where each element from 111 to nnn occurs exactly once.

For a fixed positive integer ddd , let’s define the cost of the permutation ppp of length nnn as the number of indices iii (1≤i<n)(1 \le i < n)(1≤i<n) such that pi⋅d=pi+1p_i \cdot d = p_{i + 1}pi​⋅d=pi+1​ .

For example, if d=3d = 3d=3 and p=[5,2,6,7,1,3,4]p = [5, 2, 6, 7, 1, 3, 4]p=[5,2,6,7,1,3,4] , then the cost of such a permutation is 222 , because p2⋅3=p3p_2 \cdot 3 = p_3p2​⋅3=p3​ and p5⋅3=p6p_5 \cdot 3 = p_6p5​⋅3=p6​ .

Your task is the following one: for a given value nnn , find the permutation of length nnn and the value ddd with maximum possible cost (over all ways to choose the permutation and ddd ). If there are multiple answers, then print any of them.

输入格式

The first line contains a single integer ttt ( 1≤t≤5001 \le t \le 5001≤t≤500 ) — the number of test cases.

The single line of each test case contains a single integer nnn ( 2≤n≤2⋅1052 \le n \le 2 \cdot 10^52≤n≤2⋅105 ).

The sum of nnn over all test cases does not exceed 2⋅1052 \cdot 10^52⋅105 .

输出格式

For each test case, print the value ddd in the first line, and nnn integers in the second line — the permutation itself. If there are multiple answers, then print any of them.

样例 #1

样例输入 #1

2
2
3

样例输出 #1

2
1 2
3
2 1 3

解析

这道题就是最大化数组后一个数是前一个数的倍数的个数,那么可以直接贪心2倍是最多的。因为这道题不需要ddd最大化(样例纯误导人)就算最大化答案不是222就是333,所以本代码的写法更为复杂且没用。直接从小到大枚举倍数模拟即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, m;
bool st[N];
void solve()
{scanf("%d", &n);int maxv = 0;int w = log2(n);int r = 0, cnt = 0;if(n >= 3) {r = 3, cnt = 1;while(r <= n){r = r * 3;if(r <= n) cnt ++;}}else cnt = 0;//cout << w << " " << cnt << endl;int x = cnt;for(int i = 1; i <= n; i ++) st[i] = 0;if(x == w || w < x){puts("3");printf("1 ");r = 3;while(r <= n){st[r] = 1;printf("%d ", r);r = r * 3;}for(int i = 2; i <= n; i ++){for(int j = i; j <= n; j *= 3){if(st[j]) continue;else{st[j] = true;printf("%d ", j);}}}}else{puts("2");printf("1 ");for(int i = 2; i <= n; i ++){for(int j = i; j <= n; j *= 2){if(st[j]) continue;else{st[j] = true;printf("%d ", j);}}}}printf("\n");
}
int main()
{int t;cin >> t;while(t --){solve();}
}

C Schedule Management

题面翻译

题意简述

有 nnn 个工人和 mmm 个任务,每个任务都有且仅有一个工人擅长做,如果让擅长做的工人去做,那么要花一个单位时间,否则要花两个单位时间。请问完成所有的任务至少要花多少时间。

注意:每项工作只能由一个工人完成,不能合作完成。

输入格式

本题多测,对于每组数据,第一行两个整数 nnn 和 mmm。第二行 mmm 个数,表示每项工作所擅长的工人编号。

输出格式

每组数据一个整数表示最少要花的时间。

题目描述

There are nnn workers and mmm tasks. The workers are numbered from 111 to nnn . Each task iii has a value aia_iai​ — the index of worker who is proficient in this task.

Every task should have a worker assigned to it. If a worker is proficient in the task, they complete it in 111 hour. Otherwise, it takes them 222 hours.

The workers work in parallel, independently of each other. Each worker can only work on one task at once.

Assign the workers to all tasks in such a way that the tasks are completed as early as possible. The work starts at time 000 . What’s the minimum time all tasks can be completed by?

输入格式

The first line contains a single integer ttt ( 1≤t≤1041 \le t \le 10^41≤t≤104 ) — the number of testcases.

The first line of each testcase contains two integers nnn and mmm ( 1≤n≤m≤2⋅1051 \le n \le m \le 2 \cdot 10^51≤n≤m≤2⋅105 ) — the number of workers and the number of tasks.

The second line contains mmm integers a1,a2,…,ama_1, a_2, \dots, a_ma1​,a2​,…,am​ ( 1≤ai≤n1 \le a_i \le n1≤ai​≤n ) — the index of the worker proficient in the iii -th task.

The sum of mmm over all testcases doesn’t exceed 2⋅1052 \cdot 10^52⋅105 .

输出格式

For each testcase, print a single integer — the minimum time all tasks can be completed by.

样例 #1

样例输入 #1

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

样例输出 #1

2
3
1
1

提示

In the first testcase, the first worker works on tasks 111 and 333 , and the second worker works on tasks 222 and 444 . Since they both are proficient in the corresponding tasks, they take 111 hour on each. Both of them complete 222 tasks in 222 hours. Thus, all tasks are completed by 222 hours.

In the second testcase, it’s optimal to assign the first worker to tasks 1,21, 21,2 and 333 and the second worker to task 444 . The first worker spends 333 hours, the second worker spends 222 hours (since they are not proficient in the taken task).

In the third example, each worker can be assigned to the task they are proficient at. Thus, each of them complete their task in 111 hour.

解析

这道题需要我们算出工人工作的最短时间,我们需要迅速反应出这道题的时间具有二分性。因为最短时间之前做不完,最短时间及以后都能做完,那么我们就需要去O(n)O(n)O(n)检查是否做完就行了。假设有时间ttt然后第iii擅长aia_iai​个工作,那么让w=min(t,a[i])w=min(t,a[i])w=min(t,a[i]),如果w==a[i]w==a[i]w==a[i]那么还有空余时间,空余时间可以做t−w2\frac{t-w}{2}2t−w​个任务。否则还需要(t−w)(t-w)(t−w)的工作需要做完(注意不是时间)。然后其他同理,如果空余的任务数大于等于需要做完的任务,那么就可以做。代码实现较为容易,需要注意开longlonglonglonglonglong。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, m;
int a[N];bool check(ll t)
{ll re = 0;ll nt = 0;for(int i = 1; i <= n; i ++){ll w = min(t, 1ll * a[i]);if(w == a[i]){re += (t - w) / 2;}else{nt += (a[i] - w);}}//printf("%d %d %d\n", re, nt, t);if(re >= nt) return true;else return false;
}
void solve()
{scanf("%d %d", &n, &m);for(int i = 1; i <= n; i ++) a[i] = 0;for(int i = 1; i <= m; i ++){int t;scanf("%d", &t);a[t] ++;}int l = 1, r = 2 * m;while(l < r){int mid = l + r >> 1;if(check(mid)) r = mid;else l = mid + 1;}printf("%d\n", l);
}
int main()
{int t;cin >> t;while(t --){solve();}
}

D Permutation Restoration

题目描述

Monocarp had a permutation aaa of nnn integers 111 , 222 , …, nnn (a permutation is an array where each element from $ 1 $ to $ n $ occurs exactly once).

Then Monocarp calculated an array of integers bbb of size nnn , where bi=⌊iai⌋b_i = \left\lfloor \frac{i}{a_i} \right\rfloorbi​=⌊ai​i​⌋ . For example, if the permutation aaa is [2,1,4,3][2, 1, 4, 3][2,1,4,3] , then the array bbb is equal to [⌊12⌋,⌊21⌋,⌊34⌋,⌊43⌋]=[0,2,0,1]\left[ \left\lfloor \frac{1}{2} \right\rfloor, \left\lfloor \frac{2}{1} \right\rfloor, \left\lfloor \frac{3}{4} \right\rfloor, \left\lfloor \frac{4}{3} \right\rfloor \right] = [0, 2, 0, 1][⌊21​⌋,⌊12​⌋,⌊43​⌋,⌊34​⌋]=[0,2,0,1] .

Unfortunately, the Monocarp has lost his permutation, so he wants to restore it. Your task is to find a permutation aaa that corresponds to the given array bbb . If there are multiple possible permutations, then print any of them. The tests are constructed in such a way that least one suitable permutation exists.

输入格式

The first line contains a single integer ttt ( 1≤t≤1051 \le t \le 10^51≤t≤105 ) — number of test cases.

The first line of each test case contains a single integer nnn ( 1≤n≤5⋅1051 \le n \le 5 \cdot 10^51≤n≤5⋅105 ).

The second line contains $ n $ integers b1,b2,…,bnb_1, b_2, \dots, b_nb1​,b2​,…,bn​ ( 0≤bi≤n0 \le b_i \le n0≤bi​≤n ).

Additional constrains on the input:

  • the sum of $ n $ over test cases does not exceed 5⋅1055 \cdot 10^55⋅105 ;
  • there exists at least one permutation aaa that would yield this array bbb .

输出格式

For each test case, print nnn integers — a permutation aaa that corresponds to the given array bbb . If there are multiple possible permutations, then print any of them.

样例 #1

样例输入 #1

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

样例输出 #1

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

解析

这道题告诉我们bbb数组我们需要通过转换求出一组排列aaa使得满足对任意(1≤i≤n)bi=⌊iai⌋(1\le i \le n) b_i = \left\lfloor \frac{i}{a_i} \right\rfloor(1≤i≤n)bi​=⌊ai​i​⌋。我们可以知道每一个aia_iai​的值范围。如果已一个数满足bi=⌊iai⌋b_i = \left\lfloor \frac{i}{a_i} \right\rfloorbi​=⌊ai​i​⌋那么ai∈[ibi+1+1,ibi]a_i\in[\frac{i}{b_i+1}+1,\frac{i}{b_i}]ai​∈[bi​+1i​+1,bi​i​]。这样我们就可以在O(n)O(n)O(n)的时间算出每一个位置的数的取值范围。现在问题就转化成为,给出nnn个数的范围,然后找到一个合法的排列使得每一个关系都成立。这个问题是一个比较经典的问题,叫做活动安排。从直观上讲,应该是按照右边界作为第一关键字排序,做边界作为第二关键字。开一个vector[N]vector[N]vector[N]来存以L开始的所有范围。然后枚举111到nnn,把所有以iii开始的所有范围按照[R,pos][R,pos][R,pos]的格式存到优先队列当中,那么这样安排一定是最优的,因为它满足了我每一次分配的是“最需要”的节点。然后将ans[pos]=ians[pos]=ians[pos]=i即可,然后输出所有答案。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + 10;
int n, m;
typedef pair<int,int> PII;
int b[N];
vector<PII> g[N];
priority_queue<PII,vector<PII>, greater<PII>> heap;
int a[N];
void solve()
{scanf("%d", &n);for(int i = 1; i <= n; i ++){g[i].clear();}for(int i = 1; i <= n; i ++){scanf("%d", &b[i]);}for(int i = 1; i <= n; i ++){int L = i / (b[i] + 1) + 1;int R = b[i] == 0 ? n : i / b[i];g[L].push_back({R, i});}for(int i = 1; i <= n; i ++){for(PII p:g[i]) heap.push(p);PII p = heap.top();heap.pop();a[p.second] = i;}for(int i = 1; i <= n; i ++){printf("%d ", a[i]);}printf("\n");
}
int main()
{int t;cin >> t;while(t --){solve();}
}

E Text Editor

题目描述

You wanted to write a text ttt consisting of mmm lowercase Latin letters. But instead, you have written a text sss consisting of nnn lowercase Latin letters, and now you want to fix it by obtaining the text ttt from the text sss .

Initially, the cursor of your text editor is at the end of the text sss (after its last character). In one move, you can do one of the following actions:

  • press the “left” button, so the cursor is moved to the left by one position (or does nothing if it is pointing at the beginning of the text, i. e. before its first character);
  • press the “right” button, so the cursor is moved to the right by one position (or does nothing if it is pointing at the end of the text, i. e. after its last character);
  • press the “home” button, so the cursor is moved to the beginning of the text (before the first character of the text);
  • press the “end” button, so the cursor is moved to the end of the text (after the last character of the text);
  • press the “backspace” button, so the character before the cursor is removed from the text (if there is no such character, nothing happens).

Your task is to calculate the minimum number of moves required to obtain the text ttt from the text sss using the given set of actions, or determine it is impossible to obtain the text ttt from the text sss .

You have to answer $ T $ independent test cases.

输入格式

The first line of the input contains one integer TTT ( 1≤T≤50001 \le T \le 50001≤T≤5000 ) — the number of test cases. Then TTT test cases follow.

The first line of the test case contains two integers nnn and mmm ( 1≤m≤n≤50001 \le m \le n \le 50001≤m≤n≤5000 ) — the length of sss and the length of ttt , respectively.

The second line of the test case contains the string sss consisting of nnn lowercase Latin letters.

The third line of the test case contains the string ttt consisting of mmm lowercase Latin letters.

It is guaranteed that the sum of nnn over all test cases does not exceed 500050005000 ( ∑n≤5000\sum n \le 5000∑n≤5000 ).

输出格式

For each test case, print one integer — the minimum number of moves required to obtain the text ttt from the text sss using the given set of actions, or -1 if it is impossible to obtain the text ttt from the text sss in the given test case.

样例 #1

样例输入 #1

6
9 4
aaaaaaaaa
aaaa
7 3
abacaba
aaa
5 4
aabcd
abcd
4 2
abba
bb
6 4
baraka
baka
8 7
question
problem

样例输出 #1

5
6
3
4
4
-1

解析

这道题先看数据范围,n≤5000n\le5000n≤5000时间复杂度就是n2n^2n2,根据学习动态规划的经验,有一道动态规划叫做编辑距离,这道题和本题非常相似,所以通过动态规划来解决这道题。这道题有几种操作,第一种是将光标移到左边一格,第二种是把光标移到右边一格,第三种是把光标移到最左边,第四种是把光标移到最右边,最后一种是删除光标前面的一段字符。光标一开始是在最右边,那么通过贪心的想法,删除操作肯定不包含将光标移到最右边,应该是从右删除到左,然后突然跳跃一段距离,然后从左往右删除,这样的删除顺序是最优的。所以我们需要考虑三种:从前往后删除,中间完全匹配,后面从后往前删除。那么我们可以假设dp[i][j]dp[i][j]dp[i][j]是sss串匹配了前iii为,ttt串匹配了前jjj位时的操作次数。接下来分别讨论状态转移方程的书写,下标都是0开始,注意不能越界。

1.1.1.前缀:
初始状态dp[0][0]=1dp[0][0]=1dp[0][0]=1因为光标移到前面需要操作一次,其余都是正无穷。
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+2)dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 2)dp[i+1][j]=min(dp[i+1][j],dp[i][j]+2) 未匹配上,需要光标右移一次,删除一次。
dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+1)(s[i]==t[j])dp[i + 1][j + 1]=min(dp[i + 1][j + 1], dp[i][j] + 1) (s[i] == t[j])dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+1)(s[i]==t[j])匹配上,光标右移。
2.2.2.中缀
初始状态dp[0][0]=0dp[0][0]=0dp[0][0]=0其余值不变。
dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j])(s[i]==t[j])dp[i + 1][j + 1]=min(dp[i + 1][j + 1],dp[i][j]) (s[i]==t[j])dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j])(s[i]==t[j])这一段直接跳过,所以操作数是0。
3.3.3.后缀
初始状态dp[0][0]=0dp[0][0]=0dp[0][0]=0其余值不变。
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 1)dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1) 未匹配上,需要光标删除一次。
dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+1)(s[i]==t[j])dp[i + 1][j + 1]=min(dp[i + 1][j + 1], dp[i][j] + 1) (s[i] == t[j])dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+1)(s[i]==t[j])匹配上,光标左移。

如果dp[n][m]≠INF,ans=dp[n][m]dp[n][m]\ne INF,ans = dp[n][m]dp[n][m]=INF,ans=dp[n][m],否则ans=−1ans=-1ans=−1

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5010;
int n, m;
int dp[N][N];
void solve()
{cin >> n >> m;string s, t;cin >> s >> t;for(int i = 0; i <= n; i ++){for(int j = 0; j <= m; j ++) dp[i][j] = 2e9;}dp[0][0] = 1;for(int i = 0; i <= n; i ++){for(int j = 0; j <= m; j ++){if(i < n) dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 2);if(s[i] == t[j] && i < n && j < m) dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j] + 1);}}dp[0][0] = 0;for(int i = 0; i < n; i ++){for(int j = 0; j < m; j ++){if(s[i] == t[j]) dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j]);}}dp[0][0] = 0;for(int i = 0; i <= n; i ++){for(int j = 0; j <= m; j ++){if(i < n) dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 1);if(s[i] == t[j] && i < n && j < m) dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j] + 1);}}if(dp[n][m] == 2e9){printf("-1\n");}else{printf("%d\n", dp[n][m]);}
}
int main()
{int t;cin >> t;while(t --){solve();}
}

F Points

题目描述

A triple of points iii , jjj and kkk on a coordinate line is called beautiful if i<j<ki < j < ki<j<k and k−i≤dk - i \le dk−i≤d .

You are given a set of points on a coordinate line, initially empty. You have to process queries of three types:

  • add a point;
  • remove a point;
  • calculate the number of beautiful triples consisting of points belonging to the set.

输入格式

The first line contains two integers qqq and ddd ( 1≤q,d≤2⋅1051 \le q, d \le 2 \cdot 10^51≤q,d≤2⋅105 ) — the number of queries and the parameter for defining if a triple is beautiful, respectively.

The second line contains qqq integers a1,a2,…,aqa_1, a_2, \dots, a_qa1​,a2​,…,aq​ ( 1≤ai≤2⋅1051 \le a_i \le 2 \cdot 10^51≤ai​≤2⋅105 ) denoting the queries. The integer aia_iai​ denotes the iii -th query in the following way:

  • if the point aia_iai​ belongs to the set, remove it; otherwise, add it;
  • after adding or removing the point, print the number of beautiful triples.

输出格式

For each query, print one integer — the number of beautiful triples after processing the respective query.

样例 #1

样例输入 #1

7 5
8 5 3 2 1 5 6

样例输出 #1

0
0
1
2
5
1
5

解析

这道题的要求是计算满足条件的triple的数量,假设f[i]=[i+1,i+d]f[i] = [i + 1, i + d]f[i]=[i+1,i+d]的数字的数目,那么triple的个数ans=(f[i]∗(f[i]−1)/2ans = (f[i] * (f[i]-1) / 2ans=(f[i]∗(f[i]−1)/2,那么当插入一个数字x的时候,对于[x−d,x−1][x - d, x - 1][x−d,x−1]这个区间的贡献是111,反之是−1-1−1,这道题的答案ans=∑(f[i]AND[i存在])ans = \sum(f[i] AND [i存在])ans=∑(f[i]AND[i存在]),所以说需要使用线段树维护区间加减,然后需要维护当前的答案ansansans,所以还需要维护iii后面有几个数www,加入k个数对答案的贡献是12∗((f[i]+k)2−(f[i]+k))−12∗(f[i]2−f[i])=k∗f[i]+k∗(k−1)2\frac{1}{2} * ((f[i] + k) ^ 2 - (f[i] + k)) - \frac{1}{2} * (f[i] ^ 2 - f[i]) = k * f[i] +\frac{ k * (k - 1)}{2}21​∗((f[i]+k)2−(f[i]+k))−21​∗(f[i]2−f[i])=k∗f[i]+2k∗(k−1)​,减去k个数对答案的贡献是12∗((f[i]+k)2−(f[i]+k))−12∗(f[i]2−f[i])=k∗f[i]−k∗(k−1)2\frac{1}{2} * ((f[i] + k) ^ 2 - (f[i] + k)) - \frac{1}{2} * (f[i] ^ 2 - f[i]) = k * f[i] -\frac{ k * (k - 1)}{2}21​∗((f[i]+k)2−(f[i]+k))−21​∗(f[i]2−f[i])=k∗f[i]−2k∗(k−1)​。

所以线段数需要维护三个值,一个是答案,一个是f[i]f[i]f[i]的和,一个是存在的数目。在修改的时候同时维护ansansans,每一次询问的答案就是tr[1].anstr[1].anstr[1].ans,需要注意的是在维护区间和的时候,加上一个常数对一个父节点的贡献是儿子的数目*常数。所以需要维护节点个数tottottot。还有就是先维护区间和,然后再是单点修改,顺序不能换。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n, m;
int st[N];
struct node
{ll sum, tot, ans;ll tag;
}tr[N * 4];void update(int id)
{tr[id].ans = tr[id * 2].ans + tr[id * 2 + 1].ans;tr[id].sum = tr[id * 2].sum + tr[id * 2 + 1].sum;tr[id].tot = tr[id * 2].tot + tr[id * 2 + 1].tot;
}void settag(int id,ll val)
{if(val > 0){tr[id].ans += val * tr[id].sum;tr[id].ans += val * (val - 1) / 2 * tr[id].tot;}else{tr[id].ans += val * tr[id].sum;ll v = -val;tr[id].ans += v * (v + 1) / 2 * tr[id].tot;}tr[id].sum += val * tr[id].tot;tr[id].tag += val;
}void pushdown(int id)
{if(tr[id].tag != 0){settag(id * 2, tr[id].tag);settag(id * 2 + 1, tr[id].tag);tr[id].tag = 0;}
}void change(int id,int l,int r,int pos, ll val, int tot)
{if(l == r){tr[id].ans = val * (val - 1) / 2;tr[id].sum = val;tr[id].tot = tot;}else{int mid = l + r >> 1;pushdown(id);if(pos <= mid) change(id * 2, l, mid, pos, val, tot);else change(id * 2 + 1, mid + 1, r, pos, val, tot);update(id);}
}void modify(int id,int l,int r,int ql,int qr,int val)
{if(l == ql && r == qr){settag(id, val);}else{int mid = l + r >> 1;pushdown(id);if(qr <= mid) modify(id * 2, l, mid, ql, qr, val);else if(ql > mid) modify(id * 2 + 1, mid + 1, r, ql, qr, val);else{modify(id * 2, l, mid, ql, mid, val);modify(id * 2 + 1, mid + 1, r, mid + 1, qr, val);}update(id);}
}int Query(int id,int l,int r,int ql,int qr)
{//cout << l << " " << r << " " << ql << " " << qr << endl;if(l == ql && r == qr){return tr[id].tot;}else{int mid = l + r >> 1;pushdown(id);if(qr <= mid) return Query(id * 2, l, mid, ql, qr);else if(ql > mid) return Query(id * 2 + 1, mid + 1, r, ql, qr);else{return Query(id * 2, l, mid, ql, mid) + Query(id * 2 + 1, mid + 1, r, mid + 1, qr);}update(id);}
}int main()
{int d;scanf("%d %d", &n, &d);for(int i = 1; i <= n; i ++){int w;scanf("%d" ,&w);if(st[w]){modify(1, 1, N - 5, max(w - d, 1), w, -1);change(1, 1, N - 5, w, 0, 0);}else{modify(1, 1, N - 5, max(w - d, 1), w, 1);ll res = Query(1, 1, N - 5, w, min(N - 5, w + d));change(1, 1, N - 5, w, res, 1);}st[w] ^= 1;printf("%lld\n", tr[1].ans);}return 0;
}

评价

我认为这场比赛作为教育场十分具有教育意义。A,B题考查贪心,C考察二分,D考察经典模型,E题考察编辑距离为模型的动态规划问题。F则是线段树维护区间和的应用。可以说每道题都非常有意义,巩固了基础知识和数据结构,还训练了动态规划问题。

Educational Codeforces Round 131 (Rated for Div. 2)刷题记录OR题解相关推荐

  1. Educational Codeforces Round 100 (Rated for Div. 2)补题记录

    总结:感觉这个educational场好难啊(蒟蒻视角),又被虐了,唉 A. Dungeon 每一枪会造成1点伤害对一个单位,但是当开7的倍数枪时会造成3点伤害 每7次一个轮回,一个完整的轮回共造成9 ...

  2. Educational Codeforces Round 106 (Rated for Div. 2)(A ~ E)题解(每日训练 Day.16 )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 Educational Codeforces Round 106 (Rated for Div. ...

  3. Educational Codeforces Round 103 (Rated for Div. 2)前四题

    Educational Codeforces Round 103 (Rated for Div. 2) 第二次被别人hack,悲 A - K-divisible Sum 题意 给定两个整数 n,kn, ...

  4. Educational Codeforces Round 131 (Rated for Div. 2) A-D题解

    题目 A. Grass Field B. Permutation C. Schedule Management D. Permutation Restoration A. Grass Field 题解 ...

  5. Educational Codeforces Round 133 (Rated for Div. 2) D题

    题目链接:Problem - D - Codeforces 一道非常经典的完全背包求方案数题: 首先先写好我们的状态转移方程,那什么代表体积,什么代表物品数目呢: 其实很清晰k, k + 1 ... ...

  6. codeforces Educational Codeforces Round 49 (Rated for Div. 2) C题

    刚开始拿到这题很懵逼,知道了别人的思路之后开始写,但是还是遇到很多坑,要求求P2/S最大.p=a b.就是求(a2+ b2 +2ab)/ab最大,也就是a/b +b/a最大.那么题意就很明显了. 但是 ...

  7. Educational Codeforces Round 119 (Rated for Div. 2) 做题日志

    A Equal or Not Equal 题意 给你一个字符串, s i = = E si == E si==E表示 a ( i ) = = a ( i + 1 ) a(i) == a(i+1) a( ...

  8. Educational Codeforces Round 33 (Rated for Div. 2) B题

    B. Beautiful Divisors Recently Luba learned about a special kind of numbers that she calls beautiful ...

  9. Educational Codeforces Round 74 (Rated for Div. 2)

    Educational Codeforces Round 74 (Rated for Div. 2) 原题地址 # 题目 分数 是否AC A Prime Subtraction 900 ✅ B Kil ...

最新文章

  1. 等概率随机函数的实现
  2. linux下mvn的运行配置,Linux内网环境下使用Nexus配置Maven私有仓库
  3. ORM for Net主流框架汇总与效率测试
  4. jvm相关參数,调优
  5. Java面试11|Maven与Git
  6. 海龟绘图两小时上手C语言 - 0 引言
  7. C语言创建学生姓名分数链表,C语言编程 编写程序,建立一个学生数据链表,学生的数据包括学号、姓名、成绩。...
  8. 伪静态在webconfig中配置
  9. Rhythmk 学习 Hibernate 03 - Hibernate 之 延时加载 以及 ID 生成策略
  10. CSS选择器之基本选择器总结
  11. DevComponents.DotNetBar2 美化包使用以及验证教程
  12. JVM(1.8)GC日志解析与分析
  13. 使用RamDiskNT虚拟软盘后vmware无法识别
  14. uniapp打开外部链接
  15. word2016撤销无效解决办法
  16. 关闭烦人的wps广告
  17. 国外成熟的程序交易系统的思路 z
  18. 亚马逊云科技蝉联中国数据管理解决方案领导者
  19. 基于Python实现的电梯进程及调度管理
  20. 安装编译好的Android镜像到模拟器上 (android 7.0)

热门文章

  1. 90后、00后都开始喝茶养生了
  2. 利用matlab调用cplex求解器时遇到猫图是什么原因呢
  3. iOS杂谈14—iOS设备的UDID是什么?苹果为什么拒绝获取iOS设备UDID的应用?如何替代UDID?
  4. 或许是时候说一声再见
  5. 使用CNN/ResNet实现自动调制识别(RML2018.01a)
  6. 宇宙:一些有趣的数字
  7. html5图灵机器人自动会话代码,Vue结合图灵机器人制作的一个简单的仿微信聊天的自动回复机器人...
  8. 连锁不平衡LD以及相关式子的推导
  9. 如何在计算机显示扫描仪错误,柯达扫描仪故障解决办法【详解】
  10. JAVA支付宝扫码支付开发流程