zoukankan      html  css  js  c++  java
  • [洛谷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;
    }
    
  • 相关阅读:
    Java实现 LeetCode 382 链表随机节点
    Java实现 LeetCode 382 链表随机节点
    Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素
    Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素
    Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素
    Java实现 LeetCode 380 常数时间插入、删除和获取随机元素
    Java实现 LeetCode 380 常数时间插入、删除和获取随机元素
    Linux下的iwpriv(iwlist、iwconfig)的简单应用
    OCX控件的注册卸载,以及判断是否注册
    .OCX、.dll文件注册命令Regsvr32的使用
  • 原文地址:https://www.cnblogs.com/skylee03/p/9379168.html
Copyright © 2011-2022 走看看