[ACM]CCF CSP [201709-5]E题 除法
2017-10-14 19:57
253 查看
思路:
(1)对于每一个可能的因子(2..100万),记录是其倍数的所有数的下标,对于某个询问[l,r,v],找出l,r中所有为v倍数的数,除掉就好了。
(2)维护一个树状数组,修改值以及统计区间和。
这样仍然会超时,加了个优化,(1)中这些因子如果没在询问1中的v出现过(而v最多有10万个不同的),就不用记录。这样可以过所有数据。
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<stdio.h>
#include<set>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1010000
set<int> s
;
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<int>::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
;
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<N;i++) if (existV[i]) printf("%d ",i) ;putchar('\n');
for (int i=1;i<=n;i++){
int tmp=a[i];
for (int j=1;j*j<=tmp;j++){
int p=tmp/j;
if (j*p!=tmp)continue; //j*p=tmp && j<=p
if (j!=1 && existV[j])s[j].insert(i);
if (p!=j && existV[p])s[p].insert(i);
}
}
return 0;
}
int main(){
read();
for (int i=1;i<=m;i++){
if (op[i]==1){
div(l[i],r[i],v[i]);
}else{
cout<<bit_sum(l[i],r[i])<<endl;
}
}
return 0;
}
(1)对于每一个可能的因子(2..100万),记录是其倍数的所有数的下标,对于某个询问[l,r,v],找出l,r中所有为v倍数的数,除掉就好了。
(2)维护一个树状数组,修改值以及统计区间和。
这样仍然会超时,加了个优化,(1)中这些因子如果没在询问1中的v出现过(而v最多有10万个不同的),就不用记录。这样可以过所有数据。
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<stdio.h>
#include<set>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1010000
set<int> s
;
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<int>::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
;
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<N;i++) if (existV[i]) printf("%d ",i) ;putchar('\n');
for (int i=1;i<=n;i++){
int tmp=a[i];
for (int j=1;j*j<=tmp;j++){
int p=tmp/j;
if (j*p!=tmp)continue; //j*p=tmp && j<=p
if (j!=1 && existV[j])s[j].insert(i);
if (p!=j && existV[p])s[p].insert(i);
}
}
return 0;
}
int main(){
read();
for (int i=1;i<=m;i++){
if (op[i]==1){
div(l[i],r[i],v[i]);
}else{
cout<<bit_sum(l[i],r[i])<<endl;
}
}
return 0;
}
相关文章推荐
- CCF CSP认证 题解:201709-5 除法(Java语言原创)
- 【CCF-CSP 201709-1】打酱油
- 【CCF-CSP 201709-2】公共钥匙盒
- CCF CSP 201709-2 公共钥匙盒
- [ACM]CCF CSP [201509-5]E题 最佳文章【90分】
- CCF CSP 201709-4 通信网络
- CCF CSP 公共钥匙盒 JAVA 201709-2 100分
- 【CCF-CSP 201709-1】打酱油
- 【CCF-CSP 201709-2】公共钥匙盒
- CCF 201709-5 除法
- CCF CSP 201709-2 公共钥匙盒(Java-100分)
- 【CCF-CSP 201709-1】打酱油
- 【CCF-CSP 201709-2】公共钥匙盒
- CCF 201709-5 除法 c++题解
- CCF CSP 201709-2:公共钥匙盒
- 【CCF-CSP 201709-1】打酱油
- 【CCF-CSP 201709-2】公共钥匙盒
- CCF CSP真题——201709-3 json查询
- 【CCF-CSP 201709-1】打酱油
- 【CCF-CSP 201709-2】公共钥匙盒