您的位置:首页 > 其它

2015多校赛第一场

2015-07-22 13:58 127 查看
A题

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

#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define mod 1000000000+7
#define N 100000+5
using namespace std;

int x
, y
, a
, p[10005];
vector<int>mul[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 <iostream>
#include <algorithm>
#include <cmath>
#define N 100000+50
using namespace std;

int a
;
int maxx
[20], minx
[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: