2015多校赛第一场

A题

给你个n个数的数列,找出所有区间内不能被区间其他数整除的数的个数之和。

#pragma warning(disable:4996)
#include 
#include 
#include 
#include 
#define mod 1000000000+7
#define N 100000+5
using namespace std;

int x[N], y[N], a[N], p[10005];
vectormul[10005];
int n;

int main(){
	//填充因子vector
	for (int i = 1; i <= 10000; i++){

		for (int j = 1; j <= i; j++){
			if (i%j == 0)mul[i].push_back(j);
		}
	}

	while (scanf("%d", &n) != EOF){
		for (int i = 1; i <= n; i++){
			scanf("%d", a + i);
			//初始化x,y数组
			x[i] = 0;
			y[i] = n + 1;
		}

		//此时p[i]表示i出现的左最靠近当前数字的位置
		memset(p, 0, sizeof(p));

		for (int i = 1; i <= n; i++){
			int tmp = 0;
			for (int j = 0; j < mul[a[i]].size(); j++){
				tmp = max(tmp, p[mul[a[i]][j]]);
			}
			//填充x数组
			x[i] = tmp;
			//更新p数组
			p[a[i]] = i;
		}

		for (int i = 0; i < 10005; i++)p[i] = n + 1;

		for (int i = n; i >= 1; i--){
			int tmp = n + 1;
			for (int j = 0; j < mul[a[i]].size(); j++){
				tmp = min(tmp, p[mul[a[i]][j]]);
			}
			//填充y数组
			y[i] = tmp;
			//更新p数组
			p[a[i]] = i;
		}

		int ans = 0;

		for (int i = 1; i <= n; i++){
			ans += ((i - x[i])*(y[i] - i));
			ans %= mod;
		}
		cout << ans << endl;
	}
	return 0;
}


B题

RMQ问题,ST算法+二分

先用ST算法求出区间最值(最大值和最小值),然后枚举区间左端点,二分右端点

#include 
#include 
#include 
#define N 100000+50
using namespace std;

int a[N];
int maxx[N][20], minx[N][20];

void rmq(int n){
	for (int i = 1; i <= n; i++)maxx[i][0] = minx[i][0] = a[i];

	for (int j = 1; j < 20; j++){
		for (int i = 1; i <= n; i++){
			if (i + (1 << j - 1) <= n){
				maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << j - 1)][j - 1]);
				minx[i][j] = min(minx[i][j - 1], minx[i + (1 << j - 1)][j - 1]);
			}
		}
	}
}

int query(int l, int r){
	int base = 0;
	while ((1 << (base + 1)) < (r - l + 1)) base++;
	int maxn = max(maxx[l][base], maxx[r + 1 - (1 << base)][base]);
	int minn = min(minx[l][base], minx[r + 1 - (1 << base)][base]);
	return maxn - minn;
}

int main(){
	int t;
	cin >> t;
	while (t--){
		int n, k;
		cin >> n >> k;
		for (int i = 1; i <= n; i++)cin >> a[i];

		rmq(n);
		long long ans = 0;
		for (int i = 1; i <= n; i++){
			int l = i, r = n;
			while (l <= r){
				int mid = (l + r) / 2;
				if (query(i, mid) >= k)
					r = mid - 1;
				else l = mid + 1;
			}
			ans += (r - i + 1);

		}

		cout << ans << endl;
	}
	return 0;
}


你可能感兴趣的:(2015多校赛第一场)