zoukankan      html  css  js  c++  java
  • P5610 [Ynoi2013] 大学

    题目

    P5610 [Ynoi2013] 大学

    分析

    似乎是个简单题,容易想到势能分析,每一个点最多被除 (log) 次。

    于是问题变成快速找到一个数的所有倍数的位置。

    直接对每一个数开一个 (set) 存其倍数集合,找到后可以判断是否删掉,也就是区间删除,可以并查集实现。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    #define ll long long
    const int N=5e5+5;
    int n,m,a[N],cnt[N],Max,*d[N],node[N*605],*tp=node;
    ll c[N],Ans;
    inline void Add(int x,const ll v){for(;x<=n;x+=(x&(-x))) c[x]+=v;return ;}
    inline ll Ask(int x){ll res=0;for(;x;x-=(x&(-x))) res+=c[x];return res;}
    struct DSU{
    	int *fa;
    	inline void Init(const int n){for(register int i=0;i<n;i++) fa[i]=i;}
    	inline int Getfa(int x){
    		int t1,t2=x;
    		while(x!=fa[x]) x=fa[x];
    		while(t2!=fa[t2]) t1=fa[t2],fa[t2]=x,t2=t1; 
    		return x;
    	}
    }nex[N];
    inline void Modify(int l,int r,const int x){
    	l=lower_bound(d[x],d[x]+cnt[x],l)-d[x];
    	r=upper_bound(d[x],d[x]+cnt[x],r)-d[x]-1;
    	if(l>r) return ;
    	for(register int u=nex[x].Getfa(l);u<=r;u=nex[x].Getfa(u+1)){
    		int t=d[x][u];
    		if(a[t]%x==0) Add(t,a[t]/x-a[t]),a[t]/=x;
    		if(u>=r) break;
    		if(a[t]%x) nex[x].fa[u]=nex[x].Getfa(u+1);
    	}
    	return ;
    }
    
    int main(){
    	read(n);read(m);
    	for(register int i=1;i<=n;i++) read(a[i]),Add(i,a[i]),cnt[a[i]]++,Max=max(Max,a[i]);
    	for(register int i=1;i<=Max;i++) for(int j=i+i;j<=Max;j+=i) cnt[i]+=cnt[j];
    	for(register int i=1;i<=Max+1;i++) if(cnt[i]) d[i]=tp,tp+=cnt[i],nex[i].fa=tp,nex[i].Init(cnt[i]),tp+=cnt[i],cnt[i]=0;
    	for(register int i=1;i<=n;i++) for(int j=1;j*j<=a[i];j++) if(a[i]%j==0){d[j][cnt[j]++]=i;if(j*j!=a[i]) d[a[i]/j][cnt[a[i]/j]++]=i;}
    	int op,l,r,x;
    	for(register int i=1;i<=m;i++){
    		read(op);read(l);read(r);
    		l^=Ans,r^=Ans;
    		if(op==1){read(x);x^=Ans;if(x==1) continue;Modify(l,r,x);}
    		else write(Ans=Ask(r)-Ask(l-1)),puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    HTML导航
    html5学习笔记
    crm使用soap启用和停用记录
    crmjs区分窗口是否是高速编辑(2)
    关于strace的一点东西
    Android studio第一次使用配置(三)gradle项目构建
    IntelliJ IDEA 问题总结之二(待补充) —— 快捷键、主题样式、导出jar、sqlite
    spark之map与flatMap差别
    leetcode:String to Integer (atoi)
    oracle索引的操作
  • 原文地址:https://www.cnblogs.com/Akmaey/p/15167986.html
Copyright © 2011-2022 走看看