[ACM]CCF CSP [201709-5]E题 除法

思路:

(1)对于每一个可能的因子(2..100万),记录是其倍数的所有数的下标,对于某个询问[l,r,v],找出l,r中所有为v倍数的数,除掉就好了。

(2)维护一个树状数组,修改值以及统计区间和。

这样仍然会超时,加了个优化,(1)中这些因子如果没在询问1中的v出现过(而v最多有10万个不同的),就不用记录。这样可以过所有数据。

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 1010000
set s[N];
int a[N/10];
long long c[N/10];
int n,m;
int lowbit(int x){return x&-x;}
long long bit_sum(int k){
  long long ret=0;
  while (k){
    ret+=c[k];
    k-=lowbit(k);
  }
  return ret;
}
long long bit_sum(int l,int r){
  return bit_sum(r)-bit_sum(l-1);
}
int bit_set(int k,int v){
  int tmp=v-a[k];
  a[k]=v;
  while (k<=n){
    c[k]+=tmp;
    k+=lowbit(k);
  }
  return 0;
}
int div(int l,int r,int v){
  set::iterator it=s[v].lower_bound(l);
  while (it!=s[v].end() && *it<=r){
    int idx=*it;
    if (a[idx]%v==0){
      bit_set(idx,a[idx]/v);
    }
    it++;
    if (a[idx]%v!=0) s[v].erase(idx);
  }
  return 0;
}
int op[N/10],l[N/10],r[N/10],v[N/10];
bool existV[N];
int read(){
  //getp();
  memset(c,0,sizeof(c));
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++){
   int tmp;
   scanf("%d",&tmp);
   bit_set(i,tmp);
  }
  memset(existV,0,sizeof(existV));
  for (int i=1;i<=m;i++){
    scanf("%d%d%d",&op[i],&l[i],&r[i]);
    if (op[i]==1) {scanf("%d",&v[i]);existV[v[i]]=true;}
  }
  //for (int i=1;i


你可能感兴趣的:(ACM模板)