牛客小白月赛16

小雨的三角形
链接:https://ac.nowcoder.com/acm/contest/12196/B
来源:牛客网

题目描述
小雨手上有一个填满了数字的三角形。这个三角形一共有 nn 层,其中第 ii 层共有 ii个数,且第 11 个数和第 ii 个数均为 ii 。其余的数中,第 jj 个数是上一层中第 j-1j−1 个数和第 jj 个数的和。小雨想知道这个三角形第 xx 层到第 yy 层所有数的和,一共有 mm 个询问。

输入描述:
第一行两个正整数 n,mn,m,表示这个三角形的层数和询问个数。

接下来 mm 行,每行两个正整数 x,yx,y,表示一次询问。
输出描述:
输出共 mm 行,每行一个整数,表示一组询问的答案,对 10^9 + 710
9
+7 取模。
示例1
输入
复制
5 3
1 2
1 5
3 5
输出
复制
5
83
78
说明
画出这个三角形:
1
2 2
3 4 3
4 7 7 4
5 11 14 11 5
第 1 \sim 21∼2 层的和为 1 + 2 + 2 = 51+2+2=5 。

第 1 \sim 51∼5 层的和为 1 + 2 + 2 + 3 + 4 + 3 + 4 + 7 + 7+ 4 + 5 + 11 + 14 + 11 + 5 = 831+2+2+3+4+3+4+7+7+4+5+11+14+11+5=83 。

第 3 \sim 53∼5 层的和为 3 + 4 + 3 + 4 + 7 + 7+ 4 + 5 + 11 + 14 + 11 + 5 = 783+4+3+4+7+7+4+5+11+14+11+5=78 。

备注:
1 \leq n \leq 10^3,1 \leq m \leq 10^3,1 \leq x \leq y \leq n1≤n≤10
3
,1≤m≤10
3
,1≤x≤y≤n
有差的都得先取余数再加上取余数

/*                         _
                        _ooOoo_
                       o8888888o
                       88" . "88
                       (| -_- |)
                  .'  \\|     |//  `.
                 /  \\|||  :  |||//  \
                /  _||||| -:- |||||_  \
                |   | \\\  -  /'| |   |
                | \_|  `\`---'//  |_/ |
                \  .-\__ `-. -'__/-.  /
              ___`. .'  /--.--\  `. .'___
           ."" '<  `.___\_<|>_/___.' _> \"".
          | | :  `- \`. ;`. _/; .'/ /  .' ; |
          \  \ `-.   \_\_`. _.'_/_/  -' _.' /
===========`-.`___`-.__\ \___  /__.-'_.'_.-'================
 
                  Please give me AC.
*/

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(INT x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e3 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, m;
int a[N][N];
int s[N];

signed main(){ 
	gt(n), gt(m);
	
	for (int i = 1; i <= n; i ++){
		int sum = 0;
		for (int j = 1; j <= i; j ++){
			if (j == 1 || j == i)   a[i][j] = i;
			else{
				a[i][j] = a[i - 1][j] % mod + a[i - 1][j] % mod;
				a[i][j] %= mod;
			}
			sum += a[i][j];
			sum %= mod;
		}
		s[i] = s[i - 1] + sum;
		s[i] %= mod;
	}
	
	while(m --){
		int a, b;
		gt(a), gt(b);
     //   if (b < a)   cout << "0"
		cout << ((s[b] - s[a - 1]) % mod + mod) % mod << endl;
		//cout << endl;
	}

	return 0;
}

小石的海岛之旅
链接:https://ac.nowcoder.com/acm/contest/12196/C
来源:牛客网

题目描述
暑假到了,小石和小雨到海岛上玩。
从水平方向看海岛可以看成 nn个小块,每一个小块都有一个高度h_ih
i


水位一开始为 00,随着水位的上升,海岛分成了若干块。
现在有 mm 个询问,求当水位为a_ia
i

时,海岛会分成多少块。
输入描述:
第一行输入两个正整数n,mn,m,分别表示海岛小块个数和询问个数。
第二行输入 nn 个整数 h_ih
i

,表示每一块的高度。
第三行输入 mm个整数 a_ia
i

,表示每一个询问,保证输入的 a_ia
i

单调递增。
输出描述:
共 mm 行,分别对应 mm 个询问的答案。
示例1
输入
复制
7 3
1 2 3 1 2 1 3
1 2 3
输出
复制
3
2
0
说明
当水位高度为 1 时,岛屿被分成 3 块,2 3;2;3

当水位高度为 2 时,岛屿被分成 2 块:3;3 。

当水位高度为 3 时,岛屿全部被淹没,剩余 0 块 。
备注:
1 \leq n,m \leq 10^3,1 \leq h_i \leq 10^9,1 \leq a_i < a_{i + 1} \leq 10^91≤n,m≤10
3
,1≤h
i

≤10
9
,1≤a
i

<a
i+1

≤10
9

暴力双指针即可

#include<iostream>
using namespace std;
const int N = 1010;
int a[N];
int n, m;
int x;
int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++) scanf("%d", &a[i]);
    while(m--)
    {
        int res = 0;
        scanf("%d", &x);
        for(int i = 0; i < n; i++)
        {
            if(a[i] <= x) continue;
            else
            {
                int j = i;
                while(j < n && a[j] > x) j++;
                i = j - 1;
                res ++;
            }
        }
        printf("%d\n", res);
    }
}

小阳买水果
链接:https://ac.nowcoder.com/acm/contest/12196/D
来源:牛客网

题目描述
水果店里有 nn个水果排成一列。店长要求顾客只能买一段连续的水果。
小阳对每个水果都有一个喜爱程度 a_ia
i

,最终的满意度为他买到的水果的喜欢程度之和。
如果和为正(不管是正多少,只要大于 00 即可),他就满意了。
小阳想知道在他满意的条件下最多能买多少个水果。
你能帮帮他吗?
输入描述:
第一行输入一个正整数 n,表示水果总数。

第二行输入 n 个整数 a_ia
i

,表示小阳对每个水果的喜爱程度。
输出描述:
一行一个整数表示结果。(如果 1 个水果都买不了,请输出 0)
示例1
输入
复制
5
0 0 -7 -6 1
输出
复制
1
备注:
1 \leq n \leq 2 \times 10^6,|a_i| \leq 10^31≤n≤2×10
6
,∣a
i

∣≤10
3

小阳买水果
链接:https://ac.nowcoder.com/acm/contest/12196/D
来源:牛客网

题目描述
水果店里有 nn个水果排成一列。店长要求顾客只能买一段连续的水果。
小阳对每个水果都有一个喜爱程度 a_ia
i

,最终的满意度为他买到的水果的喜欢程度之和。
如果和为正(不管是正多少,只要大于 00 即可),他就满意了。
小阳想知道在他满意的条件下最多能买多少个水果。
你能帮帮他吗?
输入描述:
第一行输入一个正整数 n,表示水果总数。

第二行输入 n 个整数 a_ia
i

,表示小阳对每个水果的喜爱程度。
输出描述:
一行一个整数表示结果。(如果 1 个水果都买不了,请输出 0)
示例1
输入
复制
5
0 0 -7 -6 1
输出
复制
1
备注:
1 \leq n \leq 2 \times 10^6,|a_i| \leq 10^31≤n≤2×10
6
, ,∣a
i

∣≤10
3

有这样一个性质,如果一个序列的和是大于0的话,那么这个序列的首尾两个数的前缀和的差是大于0的,于是我们可以利用这个性质来求解,首先排序,然后维护的是前面位置的最小值,然后与当前位置取最小值即可。需要注意的有有可能前缀和本身就是大于0的,所以加一个和为0的前缀和,还要防止相等的情况,所以我们要按照位置从大到小排序

/*                         _
                        _ooOoo_
                       o8888888o
                       88" . "88
                       (| -_- |)
                  .'  \\|     |//  `.
                 /  \\|||  :  |||//  \
                /  _||||| -:- |||||_  \
                |   | \\\  -  /'| |   |
                | \_|  `\`---'//  |_/ |
                \  .-\__ `-. -'__/-.  /
              ___`. .'  /--.--\  `. .'___
           ."" '<  `.___\_<|>_/___.' _> \"".
          | | :  `- \`. ;`. _/; .'/ /  .' ; |
          \  \ `-.   \_\_`. _.'_/_/  -' _.' /
===========`-.`___`-.__\ \___  /__.-'_.'_.-'================
 
                  Please give me AC.
*/

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(INT x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 2e6 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n;
int a[N];

struct Node{
	int val;
	int pos;
	bool operator<(const Node &W)const{
		if (val == W.val)   return pos < W.pos;
		return val < W.val;
	}
}node[N];
int pos1[N];

signed main(){ 
	gt(n);
	int sum = 0;
	for (int i = 1; i <= n; i ++){
		gt(a[i]);
		sum += a[i];
		node[i] = {sum, i};
		pos1[i] = sum;
	}
	
	n ++;
	node[n] = {0, 0};
	pos1[0] = 0;
	
	sort(node + 1, node + 1 + n);
	int last = 0x3f3f3f3f;
	int ans = 0;
	
	for (int i = 1; i <= n; i ++){
	//	cout << node[i].pos << "----" << node[i].val << endl;
		last = min(last, node[i].pos);
	//	cout << last << "----" << node[i].pos << "----" << node[last].val << "----" << node[i].val << endl;
		if (last < node[i].pos && node[i].val > pos1[last])    ans = max(ans, node[i].pos - last);
	}
	
	cout << ans << endl;
	
	return 0;
}

小雨的矩阵
链接:https://ac.nowcoder.com/acm/contest/12196/E
来源:牛客网

题目描述
小雨有一个 n \times nn×n 的矩阵,起点在(1,1),终点在(n,n),只能向下或向右走,且每次只能走 1 步。矩阵上每个点都有一个点权 a_{i,j}a
i,j


求走到终点的路径有多少不同的点权和。
输入描述:
第一行,输入一个正整数 n 。
接下来 n+1 行,每行 n 个数,表示 a_{i,j}a
i,j


输出描述:
共一行,输出有多少不同的点权和。
示例1
输入
复制
2
1 5
2 4
输出
复制
2
说明
(1,1) \rightarrow (2,1) \rightarrow (2,2):和为 7 。

(1,1) \rightarrow (1,2) \rightarrow (2,2):和为 10 。(1,1)→(2,1)→(2,2):和为7。(1,1)→(1,2)→(2,2):和为10。
备注:
1 \leq n \leq 8,0 \leq a_{i,j} \leq 501≤n≤8,0≤a
i,j

≤50

爆搜即可

/*                         _
                        _ooOoo_
                       o8888888o
                       88" . "88
                       (| -_- |)
                  .'  \\|     |//  `.
                 /  \\|||  :  |||//  \
                /  _||||| -:- |||||_  \
                |   | \\\  -  /'| |   |
                | \_|  `\`---'//  |_/ |
                \  .-\__ `-. -'__/-.  /
              ___`. .'  /--.--\  `. .'___
           ."" '<  `.___\_<|>_/___.' _> \"".
          | | :  `- \`. ;`. _/; .'/ /  .' ; |
          \  \ `-.   \_\_`. _.'_/_/  -' _.' /
===========`-.`___`-.__\ \___  /__.-'_.'_.-'================
 
                  Please give me AC.
*/

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(INT x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 20;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int a[N][N];
int n;
set<int> ss;

void dfs(int x, int y, int res){
	if (x == n && y == n){
		ss.insert(res);
		return ;
	}
	
	for (int i = 0; i < 2; i ++){
		int xx = x + dx[i], yy = y + dy[i];
		if (xx > n || yy > n)    continue;
		dfs(xx, yy, res + a[xx][yy]);
	}
}

signed main(){ 
	gt(n);
	for (int i = 1; i <= n; i ++){
		for (int j = 1; j <= n; j ++){
			gt(a[i][j]);
		}
	}
	
	dfs(1, 1, a[1][1]);
	
	cout << ss.size() << endl;
	
	return 0;
}

小石的妹子
链接:https://ac.nowcoder.com/acm/contest/12196/F
来源:牛客网

题目描述
小石有 n 个妹子,每个妹子都有一个细心程度 a_ia
i

和一个热心程度 b_ib
i


小石想给她们一个重要程度 t_it
i

(重要程度为 1 表示最重要,重要程度越小表示越重要)。
如果一个妹子 i 的细心程度和热心程度都比妹子 j 大,那么妹子 i 的重要程度要大于妹子 j 的重要程度,即妹子 i 比妹子 j 重要。
流程如下:
每次从所有没有重要程度的妹子中,找到若干妹子。对于这些妹子的任意一个,需要保证没有其他妹子比她更重要。然后把她们的重要程度标为 1 。下一次再从剩下没有重要程度的妹子中找到若干妹子,依然符合上述条件,然后把她们的重要程度标为 2,……,重复直到所有妹子都有自己的重要程度。
由于妹子太多,小石忙不过来,请你帮帮他。
输入描述:
第一行输入一个正整数 n,表示妹子的数量。
接下来 n 行,每行两个正整数 a_i,b_ia
i

,b
i

,描述每个妹子的细心程度和热心程度。
保证所有的 a_ia
i

两两不等,所有的 b_ib
i

两两不等。
输出描述:
共 n 行,第 i 行输出一个正整数 t_it
i

表示第 i 个妹子的重要程度。
示例1
输入
复制
5
1 4
2 2
3 3
4 1
5 5
输出
复制
2
3
2
2
1
说明
第一轮取第 5 个妹子(5 5),因为没有其他妹子比她重要,标记为 1;

第二轮取编号为 1,3,4 的妹子,因为对于其中的任意一个妹子,都没有其他妹子比她们重要,标记为 2;

第三轮把编号为 2 的妹子标记为 3 。
备注:
1 \leq n \leq 10^5,1 \leq a_i,b_i \leq 10^91≤n≤10
5
,1≤a
i

,b
i

≤10
9

30分的做法用拓扑排序,因为两个人如果一个人比另外一个人既热心又细心的话,那么这个人一定比另外一个人靠前

/*                         _
                        _ooOoo_
                       o8888888o
                       88" . "88
                       (| -_- |)
                  .'  \\|     |//  `.
                 /  \\|||  :  |||//  \
                /  _||||| -:- |||||_  \
                |   | \\\  -  /'| |   |
                | \_|  `\`---'//  |_/ |
                \  .-\__ `-. -'__/-.  /
              ___`. .'  /--.--\  `. .'___
           ."" '<  `.___\_<|>_/___.' _> \"".
          | | :  `- \`. ;`. _/; .'/ /  .' ; |
          \  \ `-.   \_\_`. _.'_/_/  -' _.' /
===========`-.`___`-.__\ \___  /__.-'_.'_.-'================
 
                  Please give me AC.
*/

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(INT x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e5 + 10;
const int M = 1e8 + 10;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int h[N], e[M], ne[M], idx;
int a[N], b[N];
int n;
int din[N];
int cnt = 1;
int ans[N];
set<int> ss1, ss2;

void add(int a, int b){
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void topsort(){
	queue<int> q;
	for (int i = 1; i <= n; i ++){
		if (!din[i]){
			q.push(i);
			ans[i] = cnt;
		//	ss1.insert(i);
		}
	}
	
	cnt ++;
	while(q.size()){
		int t = q.front();
		q.pop();
		
		for (int i = h[t]; ~i; i = ne[i]){
			int j = e[i];
			din[j] --;
			if (din[j] == 0){
				q.push(j);
				ans[j] = ans[t] + 1;
			}
		}
	}
}

signed main(){ 
	ios;
	memset(h, -1, sizeof h);
	cin >> n;
	for (int i = 1; i <= n; i ++){
		cin >> a[i] >> b[i];
	}	
	
	for (int i = 1; i <= n; i ++){
		for (int j = 1; j <= n; j ++){
			if (a[i] < a[j] && b[i] < b[j]){
				add(j, i);
				din[i] ++;
			}
		}
	}
	
	topsort();
	
	for (int i = 1; i <= n; i ++){
		cout << ans[i] << endl;
	}
	
	return 0;
}

小石的图形
链接:https://ac.nowcoder.com/acm/contest/12196/G
来源:牛客网

题目描述
小石想在一面墙旁边建造一段长度为 n 的篱笆来围出一块地(如图)。

求最大的地的面积。
输入描述:
共一行,输入一个整数 n 。
输出描述:
共一行,输出最大面积,保留 3 位小数。
示例1
输入
复制
1
输出
复制
0.159
备注:
0 \leq n \leq 10^30≤n≤10
3

注意的是n是半圆的周长

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#define x first
//#define y second

//int dx[4] = {0, 1, 0, -1};
//int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e5 + 10;
const int M = 3e6 + 10;
const int mod = 2333;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);



signed main(){
	int n;
	cin >> n;	
	
	double ans = ((double)n * n * 1.0) / PI / 2.0;
	
	printf("%.3lf\n", ans);
	
	return 0;
}

小阳的贝壳
链接:https://ac.nowcoder.com/acm/contest/12196/H
来源:牛客网

题目描述
小阳手中一共有 n 个贝壳,每个贝壳都有颜色,且初始第 i 个贝壳的颜色为 col_icol
i

。现在小阳有 3 种操作:

1 l r x:给 [l,r][l,r] 区间里所有贝壳的颜色值加上 xx 。

2 l r:询问 [l,r][l,r] 区间里所有相邻贝壳 颜色值的差(取绝对值) 的最大值(若 l = rl=r 输出 0)。

3 l r :询问 [l,r][l,r] 区间里所有贝壳颜色值的最大公约数。
输入描述:
第一行输入两个正整数 n,mn,m,分别表示贝壳个数和操作个数。
第二行输入 nn 个数 col_icol
i

,表示每个贝壳的初始颜色。
第三到第 m + 2m+2 行,每行第一个数为 optopt,表示操作编号。接下来的输入的变量与操作编号对应。
输出描述:
共 m 行,对于每个询问(操作 2 和操作 3)输出对应的结果。
示例1
输入
复制
5 6
2 2 3 3 3
1 2 3 3
2 2 4
3 3 5
1 1 4 2
3 2 3
2 3 5
输出
复制
3
3
1
3
备注:
1 \leq n,m \leq 10^5,1 \leq col_i,x \leq 10^3,1 \leq opt \leq 3,1 \leq l \leq r \leq n1≤n,m≤10
5
,1≤col
i

,x≤10
3
,1≤opt≤3,1≤l≤r≤n

颜色的差的最大数提醒我们可以用差分数组,维护这个差分数组的最大值就是差的最大值,所有贝壳的颜色加x也可以用差分数组来维护,需要注意的是r+1必须小于等于n,防止出现问题,维护那个最大公约数,一段区间的最大公约数可以用差分数组表示,为第一个数,后面都是差分数组即可

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;



struct Segment_tree
{
	int l, r;
	int sum, gcd, maxd; 
} tr[N * 4];

int n, m;
int a[N];
int b[N];

int Gcd(int a, int b){
	return b ? Gcd(b, a % b) : a;
}

void pushup(Segment_tree &u, Segment_tree &l, Segment_tree &r)
{
	u.sum = l.sum + r.sum;
	u.gcd = Gcd(l.gcd, r.gcd);
	u.maxd = max(abs(l.maxd), abs(r.maxd));
}

void pushup(int u)
{
	pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}

void build(int u, int l, int r)
{
	if (l != r) tr[u] = {l, r};
	else
	{
		tr[u] = {l, r, a[l], abs(a[l]), abs(a[l])};
		return;
	}
	
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	
	pushup(u);
}

void modify(int u, int l, int d)
{
	if (tr[u].l == l && tr[u].r == l)
	{
		a[l] += d;
		tr[u].sum = a[l];
		tr[u].gcd = abs(a[l]);
		tr[u].maxd = abs(a[l]);
		return;
	}
	
	int mid = tr[u].l + tr[u].r >> 1;
	if (l <= mid) modify(u << 1, l, d);
	else modify(u << 1 | 1, l, d);
	
	pushup(u);
}

Segment_tree query(int u, int l, int r)
{
	if (tr[u].l >= l && tr[u].r <= r) return tr[u];
	
	int mid = tr[u].l + tr[u].r >> 1;
	if (r <= mid) return query(u << 1, l, r);
	if (l > mid) return query(u << 1 | 1, l, r);
	
	Segment_tree total, l_tree, r_tree;
	l_tree = query(u << 1, l, r);
	r_tree = query(u << 1 | 1, l, r);
	
	pushup(total, l_tree, r_tree);
	
	return total;
}

int main()
{
	cin >> n >> m;
	
	for (int i = 1; i <= n; i ++){
		cin >> b[i];
		a[i] = (b[i] - b[i - 1]);
	}
	
	build(1, 1, n);
	
	while (m --)
	{
		int op, l, r;
		cin >> op >> l >> r;
		if (op == 1){
			int x;
			cin >> x;
			modify(1, l, x);
			if (r < n)    modify(1, r + 1, -x);
		}
		else if (op == 2){
			if (l == r)    cout << "0" << endl;
			else{
				cout << query(1, l + 1, r).maxd << endl;
			}
		}
		else if (op == 3){
			if (l == r)   cout << query(1, 1, l).sum << endl;
			else cout << Gcd(query(1, 1, l).sum, query(1, l + 1, r).gcd) << endl;
		}
	}
}


石头剪刀布
链接:https://ac.nowcoder.com/acm/contest/12196/I
来源:牛客网

题目描述
小阳和小石玩石头剪刀布的游戏,他们在地上画了 n 个长度为 1 的格子。
小阳一开始在 1 号格子,如果小阳赢了,那么他就能往前走 1 格(若在 n 号格子,则不往前走)。如果输了,就倒退 1 格(若在 1 号格子,则不往后走),平局原地不动。
小阳已经知道了他石头剪刀布赢的概率是 aa,平的概率是 bb,显然输的概率是 1-a-b1−a−b。
求小阳走到 n 号格子期望进行多少局石头剪刀布。
答案对 10^9+710
9
+7 取模。
输入描述:
第一行输入三个正整数 n,a,b,表示格子个数,小阳石头剪刀布赢的概率和平的概率。(概率已对 10^9+710
9
+7 取模)
输出描述:
共一行,输出答案。
示例1
输入
复制
50 200000002 400000003
输出
复制
630223353
备注:
1 \leq n \leq 100, 1 < a,b < 10^9 + 71≤n≤100,1<a,b<10
9
+7

石头剪刀布
链接:https://ac.nowcoder.com/acm/contest/12196/I
来源:牛客网

题目描述
小阳和小石玩石头剪刀布的游戏,他们在地上画了 n 个长度为 1 的格子。
小阳一开始在 1 号格子,如果小阳赢了,那么他就能往前走 1 格(若在 n 号格子,则不往前走)。如果输了,就倒退 1 格(若在 1 号格子,则不往后走),平局原地不动。
小阳已经知道了他石头剪刀布赢的概率是 aa,平的概率是 bb,显然输的概率是 1-a-b1−a−b。
求小阳走到 n 号格子期望进行多少局石头剪刀布。
答案对 10^9+710
9
+7 取模。
输入描述:
第一行输入三个正整数 n,a,b,表示格子个数,小阳石头剪刀布赢的概率和平的概率。(概率已对 10^9+710
9
+7 取模)
输出描述:
共一行,输出答案。
示例1
输入
复制
50 200000002 400000003
输出
复制
630223353
备注:
1 \leq n \leq 100, 1 < a,b < 10^9 + 71≤n≤100,1<a,b<10
9
+7

每个未知数表示的是从当前这个位置走到n的期望步数,推理出方程后,用高斯消元即可
**x1 x2 … xn;
x1 = (a)x2 + (1 - a)x1 + 1;
x2 = (a)x3 + (b)x2 + (1 -a - b)x1 + 1;
x3
x4 = (a)x5 + bx4 + (1 - a - b)x3 + 1;

xn= 0;
**

/*                         _
                        _ooOoo_
                       o8888888o
                       88" . "88
                       (| -_- |)
                  .'  \\|     |//  `.
                 /  \\|||  :  |||//  \
                /  _||||| -:- |||||_  \
                |   | \\\  -  /'| |   |
                | \_|  `\`---'//  |_/ |
                \  .-\__ `-. -'__/-.  /
              ___`. .'  /--.--\  `. .'___
           ."" '<  `.___\_<|>_/___.' _> \"".
          | | :  `- \`. ;`. _/; .'/ /  .' ; |
          \  \ `-.   \_\_`. _.'_/_/  -' _.' /
===========`-.`___`-.__\ \___  /__.-'_.'_.-'================
 
                  Please give me AC.
*/

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
//#include <bitsdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(INT x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 110;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, A, B;
int a[N][N];

int qmi(int a, int b){
	int res = 1;
	while(b){
		if (b & 1)   res = res % mod * a % mod;
		a = a % mod * a % mod;
		b >>= 1;
	}
	return res;
}

int ni(int x){
	return qmi(x, mod - 2);
}

int gauss()
{
    int c, r;
    for (c = 0, r = 0; c < n; c ++ )
    {
        int t = r;
        for (int i = r; i < n; i ++ )
            if (abs(a[i][c]) > abs(a[t][c]))
                t = i;

        if (abs(a[t][c]) <= 0) continue;

        for (int i = c; i < n + 1; i ++ ) swap(a[t][i], a[r][i]);
        for (int i = n; i >= c; i -- ) a[r][i] = a[r][i] * ni(a[r][c]) % mod;

        for (int i = r + 1; i < n; i ++ )
            if (abs(a[i][c]) > 0)
                for (int j = n; j >= c; j -- )
                    a[i][j] = ((a[i][j] - a[r][j] * a[i][c]) % mod + mod) % mod;

        r ++ ;
    }

    for (int i = n - 1; i >= 0; i -- )
        for (int j = i + 1; j < n; j ++ )
            a[i][n] = ((a[i][n] - a[j][n] * a[i][j]) % mod + mod) % mod;

    return 0;
}

signed main(){ 
	cin >> n >> A >> B;
	a[0][0] = mod - A;
	a[0][1] = A % mod;
	a[0][n] = -1;
	
	for (int i = 1; i < n - 1; i ++){
		a[i][i - 1] = ((1 - A - B) % mod + mod) % mod;
		a[i][i] = (B - 1 + mod) % mod;
		a[i][i + 1] = A;
		a[i][n] = -1;
	}
	
	a[n - 1][n - 1] = 1;
	
	gauss();
	
	cout << a[0][n] << endl;
		
	return 0;
}

小雨坐地铁
链接:https://ac.nowcoder.com/acm/contest/12196/J
来源:牛客网

题目描述
小雨所在的城市一共有 mm 条地铁线,分别标号为 1 号线,2 号线,……,m 号线。整个城市一共有 nn 个车站,编号为 1 \sim n1∼n 。其中坐 i 号线需要花费 a_ia
i

的价格,每坐一站就需要多花费 b_ib
i

的价格。i 号线有 c_ic
i

个车站,而且这 c_ic
i

个车站都已知,如果某一站有多条地铁线经过,则可以在这一站换乘到另一条地铁线,并且能多次换乘。现在小雨想从第 ss 个车站坐地铁到第 tt 个车站,地铁等待时间忽略不计,求最少花费的价格,若不能到达输出 -1 。(地铁是双向的,所以 ss 可能大于 tt)
输入描述:
第一行输入四个正整数 n,m,s,tn,m,s,t,分别表示车站个数,地铁线数,起点站和终点站。
第二行到第 m + 1m+1 行,每行前三个数为 a_i,b_i,c_ia
i

,b
i

,c
i

,分别表示坐 i 号线的价格,i 号线每坐一站多花的价格,i 号线车站个数。接下来 c_ic
i

个数,表示 i 号线的每一个车站的编号,单调递增。
输出描述:
共一行,一个数表示最小花费,若不能到达输出 -1 。
示例1
输入
复制
5 2 1 4
2 2 3 1 3 5
2 1 4 2 3 4 5
输出
复制
7
说明
坐 1 号线:花费 2;

1 \rightarrow 31→3:花费 2;

换乘 2 号线:花费 2;

3 \rightarrow 43→4:花费 1;

所以最小总花费为 7 。
备注:
1 \leq n \leq 10^3, 1 \leq m \leq 500,1 \leq s,t \leq n1≤n≤10
3
,1≤m≤500,1≤s,t≤n

1 \leq a_i,b_i \leq 100,1 \leq c_i \leq n,\sum\limits_{i = 1}^m c_i \leq 10^51≤a
i

,b
i

≤100,1≤c
i

≤n,
i=1

m

c
i

≤10
5

分层图,想像坐高铁的过程建立出图即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e5 + 100;
const int M = 1e6;
const int mod = 2333;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, m, s, t;

int h[M], e[M], ne[M], w[M], idx;
int dist[M];
bool st[M];

void add(int a, int b, int c){
	e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
}

void dijkstra(){
	priority_queue<PII, vector<PII>, greater<PII>> heap;
	memset(dist, 0x7f, sizeof dist);
	//cout << dist[t] << endl;
	//if (dist[t] == 0x7f7f7f7f)  cout << "------" << endl;
	dist[s] = 0;
//	st[s] = true;
	heap.push({0, s});
	
	while(heap.size()){
		auto t = heap.top();
		heap.pop();
		
		int ver = t.second, distance = t.first;
		
	//	cout << ver << " " << distance << "--------" << endl;
		if (st[ver])   continue;
		st[ver] = true;
		
		for (int i = h[ver]; ~i; i = ne[i]){
			int j = e[i];
			if (distance + w[i] < dist[j]){
				dist[j] = distance + w[i];
				heap.push({dist[j], j});
			}   
		}
	}
	
}

signed main(){
	scanf("%lld%lld%lld%lld", &n, &m, &s, &t);
	int edx = n + 1;
	
	memset(h, -1, sizeof h);
	for (int i = 1; i <= m; i ++){
		int w1, w2;
		scanf("%lld%lld", &w1, &w2);
		int cnt;
		gt(cnt);
		bool flag = false;
		while(cnt --){
			int x;
			scanf("%lld", &x);
			add(edx, x, w1), add(x, edx, 0);
		//	cout << edx << "----" << x << "----" << w1 << endl;
			if (flag){
				add(edx, edx - 1, w2);
				add(edx - 1, edx, w2);
			//	cout << edx - 1 << "---" << edx << "----" << w2 << endl;
			}
			else  flag = true;
			edx ++;
		}
	}
	
	 dijkstra();
	 if (dist[t] == 9187201950435737471)   cout << "-1" << endl;
	 else   cout << dist[t] << endl;
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值