[洛谷P3987]我永远喜欢珂朵莉~
[洛谷P3987]我永远喜欢珂朵莉~
题目大意:
给你\(n(n\le10^5)\)个数\(A_{1\sim n}(A_i\le5\times10^5)\),\(m(m\le5\times10^5)\)次操作,操作包含以下两种:
- 将区间\([l,r]\)间所有\(v\)的倍数除以\(v\)。
- 求区间\([l,r]\)所有数之和。
思路1:
对范围内要用到的每个质因数开一个
set维护包含该质因子的\(A_i\)下标。
对于操作\(1\),将\(v\)分解质因数,在
set中查找下标在\([l,r]\)中的满足条件的数。并将这些数\(\div v\)。若操作过后不包含该质因数,则将其从
set中删去。
对于操作\(2\),用树状数组维护即可。
源代码1:
#pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include<cstdio> #include<cctype> #include<vector> #include<climits> #include<sys/mman.h> #include<sys/stat.h> #include<ext/pb_ds/tree_policy.hpp> #include<ext/pb_ds/assoc_container.hpp> class MMapInput { private: char *buf,*p; int size; public: MMapInput() { register int fd=fileno(stdin); struct stat sb; fstat(fd,&sb); size=sb.st_size; buf=reinterpret_cast<char*>(mmap(0,size,PROT_READ,MAP_PRIVATE,fileno(stdin),0)); p=buf; } char getchar() { return (p==buf+size||*p==EOF)?EOF:*p++; } }; MMapInput mmi; inline int getint() { register char ch; while(!isdigit(ch=mmi.getchar())); register int x=ch^'0'; while(isdigit(ch=mmi.getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } typedef __gnu_pbds::tree<int,__gnu_pbds::null_type,std::less<int>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update> rbtree; typedef long long int64; const int N=1e5+1,M=1e5,A=1e6+1,P=78499; bool vis[A]; int a ,n,m,p,fail ; inline void sieve() { for(register int i=2;i<A;i++) { if(vis[i]) continue; p[++p[0]]=i; for(register int j=i*2;j<A;j+=i) { vis[j]=true; } } } rbtree set[P]; class FenwickTree { private: int64 val ; int lowbit(const int &x) const { return x&-x; } public: void modify(int p,const int &x) { for(;p<=n;p+=lowbit(p)) val[p]+=x; } int64 query(int p) const { int64 ret=0; for(;p;p-=lowbit(p)) ret+=val[p]; return ret; } int64 query(const int &l,const int &r) const { return query(r)-query(l-1); } }; FenwickTree t; int main() { sieve(); n=getint(),m=getint(); for(register int i=1;i<=n;i++) { a[i]=getint(); t.modify(i,a[i]); int tmp=a[i]; for(register int j=1;p[j]*p[j]<=tmp;j++) { if(tmp%p[j]==0) { set[j].insert(i); while(tmp%p[j]==0) { tmp/=p[j]; } } } if(tmp!=1) { set[std::lower_bound(&p[1],&p[p[0]]+1,tmp)-p].insert(i); } } for(register int tim=1;tim<=m;tim++) { const int opt=getint(); const int l=getint(),r=getint(); if(opt==1) { const int tmp=getint(); int v=tmp; for(register int i=1;p[i]*p[i]<=v;i++) { if(v%p[i]!=0) continue; int sum=1; for(;v%p[i]==0;v/=p[i]) sum*=p[i]; const rbtree::iterator begin=set[i].lower_bound(l); const rbtree::iterator end=set[i].upper_bound(r); if(v==1) { for(rbtree::iterator it=begin;it!=end;) { if(a[*it]%p[i]!=0) { set[i].erase(it++); continue; } if(a[*it]%tmp==0&&fail[*it]<tim) { t.modify(*it,a[*it]/tmp-a[*it]); a[*it]/=tmp; } it++; } continue; } for(rbtree::iterator it=begin;it!=end;) { if(a[*it]%p[i]!=0) { set[i].erase(it++); continue; } if(a[*it]%sum!=0) fail[*it]=tim; it++; } } if(v!=1) { const int i=std::lower_bound(&p[1],&p[p[0]]+1,v)-p; const rbtree::iterator begin=set[i].lower_bound(l); const rbtree::iterator end=set[i].upper_bound(r); for(rbtree::iterator it=begin;it!=end;) { if(a[*it]%v!=0) { set[i].erase(it++); continue; } if(a[*it]%tmp==0&&fail[*it]<tim) { t.modify(*it,a[*it]/tmp-a[*it]); a[*it]/=tmp; } it++; } } } if(opt==2) { printf("%lld\n",t.query(l,r)); } } return 0; }
思路2:
[p]本题是某年CCF-CSP原题,用当时原题的数据,上面的做法是过不了的。考虑不要按照质因数维护
set,将操作离线,对于每个\(v\)维护一个
set。然后卡卡常就过了。
源代码:
#pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include<cstdio> #include<cctype> #include<vector> #include<climits> #include<sys/mman.h> #include<sys/stat.h> #include<ext/pb_ds/assoc_container.hpp> class MMapInput { private: char *buf,*p; int size; public: MMapInput() { register int fd=fileno(stdin); struct stat sb; fstat(fd,&sb); size=sb.st_size; buf=reinterpret_cast<char*>(mmap(0,size,PROT_READ,MAP_PRIVATE,fileno(stdin),0)); p=buf; } char getchar() { return (p==buf+size||*p==EOF)?EOF:*p++; } }; MMapInput mmi; inline int getint() { register char ch; while(!isdigit(ch=mmi.getchar())); register int x=ch^'0'; while(isdigit(ch=mmi.getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } typedef long long int64; const int N=1e5+1,M=1e5,A=5e5+1; int n,a ; struct Opt { int type,l,r,v; }; Opt o[M]; std::set<int> set[M]; std::vector<int> vec; int id[A]; class FenwickTree { private: int64 val ; int lowbit(const int &x) const { return x&-x; } public: void modify(int p,const int &x) { for(;p<=n;p+=lowbit(p)) val[p]+=x; } int64 query(int p) const { int64 ret=0; for(;p;p-=lowbit(p)) ret+=val[p]; return ret; } int64 query(const int &l,const int &r) const { return query(r)-query(l-1); } }; FenwickTree t; int main() { n=getint(); const int m=getint(); for(register int i=1;i<=n;i++) { t.modify(i,a[i]=getint()); } for(register int i=0;i<m;i++) { o[i].type=getint(); o[i].l=getint(); o[i].r=getint(); if(o[i].type==1) { o[i].v=getint(); if(o[i].v==1) continue; vec.push_back(o[i].v); } } std::sort(vec.begin(),vec.end()); vec.resize(std::unique(vec.begin(),vec.end())-vec.begin()); std::fill(&id[0],&id[A],-1); for(register unsigned i=0;i<vec.size();i++) id[vec[i]]=i; for(register int i=1;i<=n;i++) { for(register int j=1;j*j<=a[i];j++) { if(a[i]%j!=0) continue; if(id[j]!=-1) set[id[j]].insert(i); if(id[a[i]/j]!=-1) set[id[a[i]/j]].insert(i); } } for(register int i=0;i<m;i++) { const int &opt=o[i].type,&l=o[i].l,&r=o[i].r; if(opt==1) { const int &v=o[i].v; if(v==1) continue; const std::set<int>::iterator begin=set[id[v]].lower_bound(l); const std::set<int>::iterator end=set[id[v]].upper_bound(r); for(register std::set<int>::iterator i=begin;i!=end;) { if(a[*i]%v!=0) { set[id[v]].erase(i++); continue; } t.modify(*i,a[*i]/v-a[*i]); a[*i]/=v; if(a[*i]%v!=0) { set[id[v]].erase(i++); continue; } ++i; } } if(opt==2) { printf("%lld\n",t.query(l,r)); } } return 0; }
- 永远不说喜欢你
- 永远不说喜欢你
- 并不是所以人都喜欢你
- 不要企图用重复的劳动代替艰苦的思考,那样永远没有进步
- 三种东西永远不要放到数据库里
- 7件女孩们永远也不知道的秘密《不过第八条你们不要看哦,看了你会后悔的…》 - Qzone日志
- 不看OCJP考题你永远不知道自己的JAVA基础有多差(三)
- 不看OCJP考题你永远不知道自己的JAVA基础有多差(六)
- 作为Web开发人员,我为什么喜欢Google Chrome浏览器
- 创业和IT精英不得不看的经典英语 喜欢英语和商务的来
- 调查显示: 英国人喜欢现金,抗拒非接触式支付
- 给喜欢生物的软件工程专业学生提建议
- 找到自己喜欢什么要做什么(四)
- 我为什么喜欢编程
- 永远不会被杀毒软件查杀的木马捆绑机
- 灯火阑珊的伤感短篇日志分享:我的伤,你永远不懂
- 三种东西永远不要放到数据库里
- 喜欢一个人行走:伤感日志
- 永远没多远、诺言是谎言:伤感日志2则
- 非常喜欢Gedit,绝不逊色EditPlus!