挑战程序设计竞赛(第二版)练习题及题解

本文介绍了如何利用克鲁斯卡尔算法解决网络连接问题,如POJ1258中计算连接所有农场所需的最小光纤长度,以及在POJ2377中寻找最贵的树形网络连接。同时,展示了如何使用二分搜索和深度优先搜索来解决相关问题。
摘要由CSDN通过智能技术生成

新手上路,大佬勿喷

持续更新,直到刷完(●'◡'●)

热身:

POJ1852

An army of ants walk on a horizontal pole of length l cm, each with a constant speed of 1 cm/s. When a walking ant reaches an end of the pole, it immediatelly falls off it. When two ants meet they turn back and start walking in opposite directions. We know the original positions of ants on the pole, unfortunately, we do not know the directions in which the ants are walking. Your task is to compute the earliest and the latest possible times needed for all ants to fall off the pole.

Input

The first line of input contains one integer giving the number of cases that follow. The data for each case start with two integer numbers: the length of the pole (in cm) and n, the number of ants residing on the pole. These two numbers are followed by n integers giving the position of each ant on the pole as the distance measured from the left end of the pole, in no particular order. All input integers are not bigger than 1000000 and they are separated by whitespace.

Output

For each case of input, output two numbers separated by a single space. The first number is the earliest possible time when all ants fall off the pole (if the directions of their walks are chosen appropriately) and the second number is the latest possible such time.

Sample Input

2
10 3
2 6 7
214 7
11 12 7 13 176 23 191

Sample Output

4 8
38 207

不用考虑两只蚂蚁碰撞过程,直接考虑每只蚂蚁分别走向两个洞口的距离,再根据题意找出最大和最小时间,因为碰撞过程可以看成两只蚂蚁交换身份,向左走的继续左走,向右走的继续右走

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int a[1000010],b[1000010];
void solve(){
	int len,n,min1,max1,mid;
	cin >> len >> n;
	for(int i = 0;i < n;i ++){
		cin >> a[i];
		b[i] = len - a[i];
	}
	sort(a,a + n);
	sort(b,b + n);
	max1 = max(a[n - 1],b[n - 1]);
	min1 = 0;
	mid = len / 2;
	for(int i = 0;i < n;i++){
		if(a[i] <= mid){
			min1 = max(min1,a[i]);
		}
		else{
			min1 = max(min1,len - a[i]);
		}
	}
	cout << min1 << " " << max1 << endl;
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t;
	cin >> t;
	while(t --){
		solve();
	}
	return 0;
}

穷竭搜索:

POJ2386

Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors.

Given a diagram of Farmer John's field, determine how many ponds he has.

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

Output

* Line 1: The number of ponds in Farmer John's field.

Sample Input

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

Sample Output

3

Hint

OUTPUT DETAILS:

There are three ponds: one in the upper left, one in the lower left,and one along the right side.

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
char mp[110][110];
int dir[8][2] = {{1,0},{1,1},{1,-1},{0,1},{0,-1},{-1,-1},{-1,0},{-1,1}}; 
int n,m;
bool check(int x,int y){
	if(x < 0 || x >= n || y < 0 || y >= m){
		return false;
	}
	return true;
}
void dfs(int x,int y){
	for(int i = 0;i < 8;i ++){
		int nx = x + dir[i][0];
		int ny = y + dir[i][1];
		if(check(nx,ny) && mp[nx][ny] == 'W'){
			mp[nx][ny] = '.';
			dfs(nx,ny);
		}
	}
	return ;
}
void solve(){
	cin >> n >> m;
	for(int i = 0;i < n;i ++){
		for(int j = 0;j < m;j ++){
			cin >> mp[i][j];
		}
	}
	int ans = 0;
	for(int i = 0;i < n;i ++){
		for(int j = 0;j < m;j ++){
			if(mp[i][j] == 'W'){
				mp[i][j] = '.';
				dfs(i,j);
				ans ++;
			}
		}
	}
	cout << ans << endl;
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	solve();
	return 0;
}
/*

*/

深度优先搜索:

POJ1979

There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.

Write a program to count the number of black tiles which he can reach by repeating the moves described above.

Input

The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.

'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.

Output

For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).

Sample Input

6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0

Sample Output

45
59
6
13

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int H,W;
int sum;
char mp[21][21];
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool check(int x,int y){
	if(x<0||x>=H||y<0||y>=W){
		return false;
	}
	return true;
}
void dfs(int x,int y){
	sum++;
	mp[x][y]='#';
	for(int i=0;i<4;i++){
		int nx=x+dir[i][0];
		int ny=y+dir[i][1];
		if(check(nx,ny)&&mp[nx][ny]=='.'){
			sum++;
			dfs(nx,ny);
		}
	}
	return ;
}
int main()
{
	while(cin>>W>>H){
		if(W==0 && H==0){
			break;
		}
		sum=1;
		int x,y;
		for(int i=0;i<H;i++){
			for(int j=0;j<W;j++){
				cin>>mp[i][j];
				if(mp[i][j]=='@'){
					x=i;
					y=j;
				}
			}
		}
		dfs(x,y);
		cout<<sum/2<<endl;
	}
	return 0;
}

最小生成树:

POJ1258

Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course.
Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.
Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.
The distance between any two farms will not exceed 100,000.

Input

The input includes several cases. For each case, the first line contains the number of farms, N (3 <= N <= 100). The following lines contain the N x N conectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem.

Output

For each case, output a single integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.

Sample Input

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0

Sample Output

28

克鲁斯卡尔模板

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n;
struct node{
	int from,to,wei;
}edge[110000];
int f[110000];
void init(){
	for(int i = 1;i <= n;i ++){
		f[i] = i;
	}
}
bool cmp(struct node x,struct node y){
	return x.wei < y.wei;
}
int find(int x){
	return x == f[x] ? x : f[x] = find(f[x]);
}
void solve(){
	init();
	int cnt = 0;
	for(int i = 1;i <= n;i ++){
		for(int j = 1;j <= n;j ++){
			int cost;
			cin >> cost;
			if(j > i){
				edge[++cnt].from = i;
				edge[cnt].to = j;
				edge[cnt].wei = cost;
			}
		}
	}
	int count = 0;
	long long ans = 0;
	sort(edge + 1,edge + 1 + cnt,cmp);
	for(int i = 1;i <= cnt;i ++){
		int x = find(edge[i].from);
		int y = find(edge[i].to);
		if(x != y){
			f[x] = y;
			ans += edge[i].wei;
			if(count == n - 1){
				break;
			}
		}
	}
	cout << ans << endl;
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	while(cin >> n && n){
		solve();
	}
	return 0;
}

POJ2377

Bessie has been hired to build a cheap internet network among Farmer John's N (2 <= N <= 1,000) barns that are conveniently numbered 1..N. FJ has already done some surveying, and found M (1 <= M <= 20,000) possible connection routes between pairs of barns. Each possible connection route has an associated cost C (1 <= C <= 100,000). Farmer John wants to spend the least amount on connecting the network; he doesn't even want to pay Bessie.

Realizing Farmer John will not pay her, Bessie decides to do the worst job possible. She must decide on a set of connections to install so that (i) the total cost of these connections is as large as possible, (ii) all the barns are connected together (so that it is possible to reach any barn from any other barn via a path of installed connections), and (iii) so that there are no cycles among the connections (which Farmer John would easily be able to detect). Conditions (ii) and (iii) ensure that the final set of connections will look like a "tree".

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..M+1: Each line contains three space-separated integers A, B, and C that describe a connection route between barns A and B of cost C.

Output

* Line 1: A single integer, containing the price of the most expensive tree connecting all the barns. If it is not possible to connect all the barns, output -1.

Sample Input

5 8
1 2 3
1 3 7
2 3 10
2 4 4
2 5 8
3 4 6
3 5 2
4 5 17

Sample Output

42

Hint

OUTPUT DETAILS:

The most expensive tree has cost 17 + 8 + 10 + 7 = 42. It uses the following connections: 4 to 5, 2 to 5, 2 to 3, and 1 to 3.

克鲁斯卡尔模板

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n,m;
struct node{
	int from,to,wei;
}edge[20010];
int f[1010];
void init(){
	for(int i = 1;i <= n;i++){
		f[i] = i;
	}
}
bool cmp(struct node x,struct node y){
	return x.wei > y.wei;
}
int find(int x){
	return x == f[x] ? x : f[x] = find(f[x]);
}
void solve(){
	cin >> n >> m;
	init();
	for(int i = 1;i <= m;i++){
		cin >> edge[i].from >> edge[i].to >> edge[i].wei;
	}
	sort(edge + 1,edge + 1 + m,cmp);
	long long ans = 0,cnt = 0;
	for(int i = 1;i <= m;i++){
		int x = find(edge[i].from);
		int y = find(edge[i].to);
		if(x != y){
			f[x] = y;
			ans += edge[i].wei;
			cnt++;
		}
	}
	if(cnt < n - 1){
		cout << "-1" << endl;
	}
	else{
		cout << ans << endl;
	}
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	solve();
	return 0;
}
/*

*/

简单数学问题:

UVA10006

An important topic nowadays in computer science is cryptography. Some people even think that cryptography is the only important field in computer science, and that life would not matter at all without cryptography. Alvaro is one of such persons, and is designing a set of cryptographic procedures for cooking paella. ´ Some of the cryptographic algorithms he is implementing make use of big prime numbers. However, checking if a big number is prime is not so easy. An exhaustive approach can require the division of the number by all the prime numbers smaller or equal than its square root. For big numbers, the amount of time and storage needed for such operations would certainly ruin the paella. However, some probabilistic tests exist that offer high confidence at low cost. One of them is the Fermat test. Let a be a random number between 2 and n−1 (being n the number whose primality we are testing). Then, n is probably prime if the following equation holds:

a ^ n mod n = a

If a number passes the Fermat test several times then it is prime with a high probability. Unfortunately, there are bad news. Some numbers that are not prime still pass the Fermat test with every number smaller than themselves. These numbers are called Carmichael numbers. In this problem you are asked to write a program to test if a given number is a Carmichael number. Hopefully, the teams that fulfill the task will one day be able to taste a delicious portion of encrypted paella. As a side note, we need to mention that, according to Alvaro, the main advantage of encrypted ´ paella over conventional paella is that nobody but you knows what you are eating.

Input

The input will consist of a series of lines, each containing a small positive number n (2 < n < 65000). A number n = 0 will mark the end of the input, and must not be processed.

Output

For each number in the input, you have to print if it is a Carmichael number or not, as shown in the sample output.

Sample Input

1729 17 561 1109 431 0

Sample Output

The number 1729 is a Carmichael number.

17 is normal.

The number 561 is a Carmichael number.

1109 is normal.

431 is normal.

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
long long n;
long long ksm(long long x, long long y,long long mod) {
	long long ans = 1;
	while (y) {
		if (y & 1) {
			ans = (ans * x) % mod;
		}
		x = (x * x) % mod;
		y >>= 1;
	}
	return ans % mod;
}
void solve() {
	while (cin >> n && n) {
		bool flag1 = false,flag2 = false;
		for (long long i = 2; i * i <= n; i++) {
			if (n % i == 0) {
				flag1 = true;
				break;
			}
		}
		if (flag1) {
			for (long long i = 2; i < n; i++) {
				if (ksm(i,n,n) != i) {
					flag2 = true;
					cout << n << " is normal." << endl;
					break;
				}
			}
			if (!flag2) {
				cout << "The number " << n << " is a Carmichael number." << endl;
			}
		}
		else {
			cout << n << " is normal." << endl;
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	solve();
	return 0;
}
/*

*/

二分搜索:

POJ1064

Inhabitants of the Wonderland have decided to hold a regional programming contest. The Judging Committee has volunteered and has promised to organize the most honest contest ever. It was decided to connect computers for the contestants using a "star" topology - i.e. connect them all to a single central hub. To organize a truly honest contest, the Head of the Judging Committee has decreed to place all contestants evenly around the hub on an equal distance from it.
To buy network cables, the Judging Committee has contacted a local network solutions provider with a request to sell for them a specified number of cables with equal lengths. The Judging Committee wants the cables to be as long as possible to sit contestants as far from each other as possible.
The Cable Master of the company was assigned to the task. He knows the length of each cable in the stock up to a centimeter,and he can cut them with a centimeter precision being told the length of the pieces he must cut. However, this time, the length is not known and the Cable Master is completely puzzled.
You are to help the Cable Master, by writing a program that will determine the maximal possible length of a cable piece that can be cut from the cables in the stock, to get the specified number of pieces.

Input

The first line of the input file contains two integer numb ers N and K, separated by a space. N (1 = N = 10000) is the number of cables in the stock, and K (1 = K = 10000) is the number of requested pieces. The first line is followed by N lines with one number per line, that specify the length of each cable in the stock in meters. All cables are at least 1 meter and at most 100 kilometers in length. All lengths in the input file are written with a centimeter precision, with exactly two digits after a decimal point.

Output

Write to the output file the maximal length (in meters) of the pieces that Cable Master may cut from the cables in the stock to get the requested number of pieces. The number must be written with a centimeter precision, with exactly two digits after a decimal point.
If it is not possible to cut the requested number of pieces each one being at least one centimeter long, then the output file must contain the single number "0.00" (without quotes).

Sample Input

4 11
8.02
7.43
4.57
5.39

Sample Output

2.00

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n,k;
double len[10010];
bool check(double x){
	int num = 0;
	for(int i = 0;i < n;i ++){
		num += (int)(len[i] / x);
	}
	return num >= k;
}
void solve(){
	for(int i = 0;i < n;i ++){
		scanf("%lf",&len[i]);
	}
	sort(len,len + n);
	double lb = 0.0;
	double ub = 1e20;
	for(int i = 0;i < 100;i ++){
		double mid = (lb + ub) / 2;
		if(check(mid)){
			lb = mid;
		}
		else{
			ub = mid;
		}
	}
	printf("%.2f\n",floor(ub * 100) / 100);
	return ;
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	while(~scanf("%d%d",&n,&k)){
		solve();
	}
	return 0;
}
/*

*/
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n,k;
void solve(){
	int len[10010];
	for(int i = 0;i < n;i ++){
		double t;
		scanf("%lf",&t);
		len[i] = t * 100.0;
	}
	int ans = 0;
	sort(len,len + n);
	int l = 1,r = len[n - 1];
	while(l <= r){
		int cnt = 0;
		int mid = (l + r) / 2;
		for(int i = 0;i < n;i ++){
			cnt += len[i] / mid;
		}
		if(cnt >= k){
			l = mid + 1;
			ans = max(ans,mid);
		}
		else{
			r = mid - 1;
		}
	}
	printf("%.2f",(double)ans / 100.0);
	return ;
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	while(~scanf("%d%d",&n,&k)){
		solve();
	}
	return 0;
}
/*

*/

POJ2456

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

* Line 1: Two space-separated integers: N and C

* Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

* Line 1: One integer: the largest minimum distance

Sample Input

5 3
1
2
8
4
9

Sample Output

3

Hint

OUTPUT DETAILS:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.

Huge input data,scanf is recommended.

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n,c;
int x[100010];
bool judge(int mid){
	int k = x[0],cnt = 1;
	for(int i = 1;i < n; i++){
		if(x[i] - k >= mid){
			cnt++;
			k = x[i];
		}
		
	}
	return cnt >= c;
}
void solve(){
	scanf("%d%d",&n,&c);
	for(int i = 0;i < n;i ++){
		scanf("%d",&x[i]);
	}
	sort(x,x + n);
	int l = 1,r = 1000000;
	for(int i = 0;i < 100;i ++){
		int mid = (l + r) / 2;
		if(judge(mid)){
			l = mid;
		}
		else{
			r = mid;
		}
	}
	cout << l << endl;
	return ;
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	
	solve();
	return 0;
}
/*

*/

线段树&树状数组:

POJ3468

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

注意防止爆int

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int maxn = 100010;
using namespace std;
int n, q;
long long tree1[maxn], tree2[maxn];
int a[maxn];
int lowbit(int x) {
	return x & -x;
}
void add(int x, int p) {
	long long v = x * p;
	for (int i = x; i <= n; i += lowbit(i)) {
		tree1[i] += p;
		tree2[i] += v;
	}
	return;
}
long long get(int x) {
	long long sum = 0;
	for (int i = x; i > 0; i -= lowbit(i)) {
		sum += (x + 1)* tree1[i] - tree2[i];
	}
	return sum;
}
void solve() {
	cin >> n >> q;
	vector<int > vec(n + 10);
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	adjacent_difference(a + 1, a + 1 + n, vec.begin() + 1);
	for (int i = 1; i <= n; i++) {
		tree1[i] += vec[i];
		tree2[i] += 1ll * i * vec[i];
		long long j = i + lowbit(i);
		if (j <= n) {
			tree1[j] += tree1[i];
			tree2[j] += tree2[i];
		}
	}
	while (q--) {
		char flag;
		cin >> flag;
		if (flag == 'C') {
			int x, y, z;
			cin >> x >> y >> z;
			add(x, z);
			add(y + 1, -z);
		}
		else {
			int x, y;
			cin >> x >> y;
			cout << get(y) - get(x - 1) << endl;
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	solve();
	return 0;
}
/*

*/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值