# 2013 ACMICPC Hangzhou Rabbit Kingdom

22 篇文章 0 订阅

## 解法

### Solution Of cxlove

这个位置就是可以的，我们 + 1 , 同时一样，他的右边位置就要 -1 ( r[pos[left][j]] ) 。

#### code

typedef long long LL;
const int N = 200005;
template<class T> inline T& RD(T &x){
//cin >> x;
//scanf("%d", &x);
char c; for (c = getchar(); c < '0'; c = getchar()); x = c - '0'; for (c = getchar(); '0' <= c && c <= '9'; c = getchar()) x = x * 10 + c - '0';
//char c; c = getchar(); x = c - '0'; for (c = getchar(); c >= '0'; c = getchar()) x = x * 10 + c - '0';
return x;
}
struct Query {
int l , r , id;
void input (int i) {
id = i;
RD(l); RD(r);
}
bool operator < (const Query &q) const {
return l < q.l;
}
}q[N];
int n , m , a[N] , s[N];
int flag[N] , prime[N] , cnt , minfac[N];
int fac[N][20] , p[N] , l[N] , r[N];
vector <int> pos[N];
void Init () {
for (int i = 2 ; i < N ; i ++) {
if (!flag[i]) {
prime[cnt ++] = i;
minfac[i] = i;
}
for (int j = 0 ; j < cnt && prime[j] * i < N ; j ++) {
flag[i * prime[j]] = 1;
minfac[i * prime[j]] = prime[j];
if (i % prime[j] == 0) break;
}
}
// minfac[1] = 1;
// fac[1][0] = 1;fac[1][1] = 1;
for (int i = 2 ; i < N ; i ++) {
fac[i][0] = 0;
int m = i;
while (m != 1) {
fac[i][++ fac[i][0]] = minfac[m];
m /= minfac[m];
}
}
}
void add (int idx , int v) {
// cout << "update : " << idx << " " << v << endl;
for (int i = idx ; i <= n ; i += lowbit (i))
s[i] += v;
}
int sum (int idx) {
int ret = 0;
for (int i = idx ; i > 0 ; i -= lowbit (i))
ret += s[i];
return ret;
}
int ans[N];
int main () {
#ifndef ONLINE_JUDGE
freopen ("input.txt" , "r" , stdin);
// freopen ("output.txt" , "w" , stdout);
#endif
Init ();
while (RD(n) , RD(m) , n + m) {
for (int i = 1 ; i <= n ; i ++)
RD(a[i]);
for (int i = 0 ; i < N ; i ++)
pos[i].clear ();
memset (p , 0 , sizeof(p));
for (int i = 1 ; i <= n ; i ++) {
int idx = 0;
for (int j = 1 ; j <= fac[a[i]][0] ; j ++)
idx = max (idx , p[fac[a[i]][j]]);
for (int j = 1 ; j <= fac[a[i]][0] ; j ++)
p[fac[a[i]][j]] = i;
l[i] = idx;
pos[idx].push_back (i);
}
memset (p , 0x11 , sizeof(p));
for (int i = n ; i > 0 ; i --) {
int idx = n + 1;
for (int j = 1 ; j <= fac[a[i]][0] ; j ++)
idx = min (idx , p[fac[a[i]][j]]);
for (int j = 1 ; j <= fac[a[i]][0] ; j ++)
p[fac[a[i]][j]] = i;
r[i] = idx;
}
for (int i = 0 ; i < m ; i ++)
q[i].input (i);
sort (q , q + m);
memset (s , 0 , sizeof(s));
for (int i = 1 ; i <= n ; i ++) {
if (l[i] < 1) {
add (i , 1);
if (r[i] <= n)
add (r[i] , -1);
}
}
int left = 1;
for (int i = 0 ; i < m ; i ++) {
while (left < q[i].l) {
add (left , -1);
if (r[left] <= n) add (r[left] , 1);
for (int j = 0 ; j < pos[left].size() ; j ++) {
add (pos[left][j] , 1);
if (r[pos[left][j]] <= n) add (r[pos[left][j]] , -1);
}
left ++;
}
ans[q[i].id] = sum (q[i].r) - sum (q[i].l - 1);
// cout << q[i].id << " " << ans[q[i].id] << " " << left << endl;
}
for (int i = 0 ; i < m ; i ++)
printf ("%d\n" , ans[i]);
}
return 0;
}


### Solution Of Dshawn

1、那么对于 first 位置的这个数，L[first] 就是一个成功的区间，那么要 L[first] + 1；
2、我用边表在 R[first] 的位置 记录他的左指针位置和他自己的位置 addR(R[first] , L[first] , first);
3、对于右区间在 first 位置的区间肯定走远了，于是我们遍历边表，找到所有R[X] = first 的区间，删掉，那么就是将对应的 L[X] - 1 ， 并且我们记录删掉了 X ， 也是用BIT 在 X的位置 +1.那么通过这一步我们就把所有右区间 <= query[i].r 的都删掉了。

#### code

int n , m;
const int N = 4e5 + 9;
using namespace Math;
struct Query{
int l , r , id;
bool operator < (const Query & A) const{
return r < A.r;
}
}query[N];
int W[N];
int L[N] , R[N];
int last[N];
int tree[N];
int deltree[N];
void delOne(int x){
for ( ; x < N ; x += low_bit(x))
deltree[x]++;
}
int querydel(int x){
int ret = 0;
for ( ; x ; x -= low_bit(x))
ret += deltree[x];
return ret;
}
struct Node{
int next;
int r;
int id;
}node[N];
int tot;
void addR(int x , int r , int id){
node[tot].r = r;
node[tot].id = id;
}
void add(int x , int y){
for ( ; x < N ; x += low_bit(x))
tree[x] += y;
}
int getsum(int x){
int ret = 0;
for ( ; x ; x -= low_bit(x))
ret += tree[x];
return ret;
}
int ans[N] , stand[N];
void debug(){
for (int i = 0 ; i < m ; ++i){
int ans = 0;
for (int j = query[i].l ; j <= query[i].r ; ++j){
bool ok = true;
for (int k = query[i].l ; k <= query[i].r ; ++k)
ok &= j == k || __gcd(W[j] , W[k]) == 1;
ans += ok;
}
stand[i] = ans;
}
}
void solve(){
n++;
for (int i = 2 ; i <= n ; ++i) {
RD(W[i]);
//            W[i] = rand() % (int)2e5 + 1;
//            printf("%d " , W[i]);
}
//    puts("");
for (int i = 0 ; i < m ; ++i){
//        scanf("%d%d" , &query[i].l , &query[i].r);
RD(query[i].l , query[i].r);
//        query[i].l = rand() % (n - 1) + 1;
//        query[i].r = query[i].l + rand() % (n - query[i].l);
//        printf("Query %d %d\n" , query[i].l , query[i].r);
query[i].l++;query[i].r++;
query[i].id = i;
}
//    debug();
sort(query , query + m);
for (int i = 1 ; i < N ; ++i) last[i] = 1;
for (int i = 2 ; i <= n ; ++i){
getFactors(W[i]);
L[i] = 1;
for (int j = 0 ; j < facCnt ; ++j){
checkMax(L[i] , last[factor[j][0]]);
last[factor[j][0]] = i;
}
}
for (int i = 1 ; i < N ; ++i) last[i] = n + 1;
for (int i = n ; i >= 2 ; --i){
getFactors(W[i]);
R[i] = n + 1;
//        cout << "factor ";
for (int j = 0 ; j < facCnt ; ++j){
//                cout << factor[j][0] << ' ';
checkMin(R[i] ,  last[factor[j][0]]);
last[factor[j][0]] = i;
}
//        cout << endl;
}
//    for (int i = 2 ; i <= n ; ++i) printf("[%d,%d]\n" , L[i] , R[i]);
//    for (int i = 2 ; i <= n ; ++i)
//        for (int j = i + 1 ; j <= n ; ++j)
//            printf("%d %d %d\n" , i , j , __gcd(W[i] , W[j]));
RST(tree);
RST(deltree);
int first = 2;
tot = 0;
for (int i = 0 ; i < m ; ++i){
while(first <= query[i].r){
addR(R[first] , L[first] , first);
for (int j = head[first] ; j != -1 ; j = node[j].next){
delOne(node[j].id);
}
first++;
}
ans[query[i].id] = query[i].r - query[i].l + 1 - (getsum(query[i].r) - getsum(query[i].l - 1) + querydel(query[i].r) - querydel(query[i].l - 1));
}
for (int i = 0 ; i < m ; ++i) {
printf("%d\n" , ans[i]);
//            if (ans[i] != stand[i]) {
//                    cout << "^^^" << endl;
//                    system("pause");
//            }
}
}
int main(){
//    srand(time(0));
getPrime();
while(RD(n , m) , (n || m)) solve();
}

• 0
点赞
• 1
收藏
觉得还不错? 一键收藏
• 打赏
• 8
评论
11-11 2340
11-11 1079
09-28 419
09-24
10-25
03-08
02-22
03-09

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

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

ACM的记忆

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

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