• [洛谷P3987]我永远喜欢珂朵莉~


    [洛谷P3987]我永远喜欢珂朵莉~

    题目大意:

    给你(n(nle10^5))个数(A_{1sim n}(A_ile5 imes10^5))(m(mle5 imes10^5))次操作,操作包含以下两种:

    1. 将区间([l,r])间所有(v)的倍数除以(v)
    2. 求区间([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],n,m,p[P],fail[N];
    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[N];
            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
    ",t.query(l,r));
            }
        }
        return 0;
    }
    

    思路2:

    本题是某年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[N];
    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[N];
    		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
    ",t.query(l,r));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    ML_入门
    subnet partition
    科比投球预测-python实例
    javascript高级程序设计》第18章 javascript与xml
    《javascript高级程序设计》第17章 错误处理与调试
    《javascript高级程序设计》 第16章 HTML5 脚本编程
    《javascript高级程序设计》 第14章 表单脚本
    《javascript高级程序设计》第13章 事件event
    《javascript高级程序设计》第12 章 DOM2 和DOM3
    《javascript高级程序设计》第11章 DOM 扩展DOM Extensions
  • 原文地址:https://www.cnblogs.com/skylee03/p/9379168.html
Copyright © 2020-2023  润新知