[Bzoj5358][Lydsy1805月赛]口算训练(预处理+动态开点线段树)

5358: [Lydsy1805月赛]口算训练


Time Limit: 5 Sec  Memory Limit: 512 MB
Submit: 318  Solved: 105
[Submit][Status][Discuss]

Description


Input


 

Output


 

Sample Input


 

Sample Output


 

HINT


 

Source


鸣谢claris提供

分析:


首先看到数最大只有10w,美滋滋,筛出素数,预处理出每个数包含哪些质数,且包含多少个。
然后对于每个质数开棵线段树。
d = (p1^c1)(p2^c2)……(pk^ck),
查询的时候只用查询d的每个质数在[L,R]范围内出现次数是否大于d中次数就行

AC代码:


# include <iostream>
# include <cstdio>
# include <cstring>
# include <vector>
# include <algorithm>
using namespace std;
const int N = 1e5;
vector<pair<int,int> > t[N + 5];
int prime[N + 5],cnt,root[N + 5],lc[N * 100],rc[N * 100],s[N * 100],p,a[N + 5];bool vis[N + 5];
void shai()
{
    for(int i = 2;i <= N;i++)
    {
        if(!vis[i])prime[++cnt] = i;
        for(int j = 1;j <= cnt;j++)
        {
            if(i * prime[j] > N)break;
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0)break;
        }
    }
    for(int i = 1;i <= cnt;i++)
     for(int j = prime[i];j <= N;j += prime[i])
     {
        t[j].push_back(make_pair(prime[i],j / prime[i]));
     }
}
void updata(int &k,int L,int l,int r,int d)
{
    if(!k){k = ++p;lc[k] = rc[k] = s[k] = 0;}
    s[k] += d;
    if(l == r)return;
    int mid = l + r >> 1;
    if(L <= mid)updata(lc[k],L,l,mid,d);
    else updata(rc[k],L,mid + 1,r,d);
}
int Query(int &k,int L,int R,int l,int r)
{
    if(!k)return 0;
    if(L <= l && r <= R)return s[k];
    int mid = l + r >> 1;
    if(L > mid)return Query(rc[k],L,R,mid + 1,r);
    if(R <= mid)return Query(lc[k],L,R,l,mid);
    return Query(lc[k],L,R,l,mid) + Query(rc[k],L,R,mid + 1,r);
}
int n,m;
int main()
{
 shai();int Case;
 scanf("%d",&Case);
 while(Case--)
 {
    memset(root,0,sizeof root);p = 0;
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&a[i]);
        for(int j = 0;j < (int)t[a[i]].size();j++)
        updata(root[t[a[i]][j].first],i,1,n,t[a[i]][j].second);
    }
    int x,y,z;
    while(m--)
    {
        scanf("%d %d %d",&x,&y,&z);bool f = true;
        for(int j = 0;j < (int)t[z].size();j++)
        if(Query(root[t[z][j].first],x,y,1,n) < t[z][j].second){f = false;break;}
        if(f)puts("Yes");else puts("No");
    }
 }
}

猜你喜欢

转载自www.cnblogs.com/lzdhydzzh/p/9098816.html