• 【莫队】【P3901】 数列找不同


    Description

    现在有一个长度为(~n~)的数列(~A_1~,~A_2~dots~A_n~)(~Q~)个询问(~[l_i~,~r_i]~),每次询问区间内是否有元素相同

    Input

    第一行有两个整数(~N,Q~),

    第二行有(~n~)个整数,代表这个序列

    以下(~Q~)行每行两个整数,代表询问区间

    Output

    对每个询问输出一行(~Yes~)(~No~)

    Hint

    (Forall:)

    (1~leq~n~,~Q~leq~10^5~,~1~leq~A_i~leq~N~,~1~leq~l_i~leq~r_i~leq~N)

    Solution

    看到这题发现可以用莫队做。然鹅统计区间出现次数平方的题写腻了,而开桶和位向量的做法又很麻烦,于是我就YY了一个更加麻烦的做法。

    发现我们可以在莫队维护区间信息的时候维护区间中所有元素出现次数之积。因为乘1等价于没有乘,我们对于没有出现的元素也乘1。这个值在指针移动时是支持修改的:只要在去掉该位置贡献的时候除掉当前的出现次数,然后将这个位置的出现次数(-1),再乘回去即可。增加一个位置贡献的方法同理。当询问的区间出现次数积为(1)时,即为没有出现重复,否则为出现重复。

    但是考虑这么做在极端数据,比如前(frac{n}{2})个数出现了(2)次,后(frac{n}{2})个数没有出现的时候,积是(2^{frac{n}{2}})次方,显然存不下。这时考虑NOIP2014解方程,我们只需要对多个形如1******7的大质数取模,当所有取模后的答案都为(1)是,我们认为积是(1),否则积显然不是(1)

    于是先(O(n))筛一下逆元再莫队就好了。

    Code

    这个代码写的好丑啊……其实可以美化美化然而我懒得写了

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #ifdef ONLINE_JUDGE
    #define puts(o) 
    puts("I am a cheater!")
    #define freopen(a,b,c)
    #endif
    #define rg register
    #define ci const int
    #define cl const long long
    
    typedef long long int ll;
    
    template <typename T>
    inline void qr(T &x) {
    	rg char ch=getchar(),lst=' ';
    	while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
    	while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	if(lst == '-') x=-x;
    }
    
    namespace IO {
    	char buf[120];
    }
    
    template <typename T>
    inline void qw(T x,const char aft,const bool pt) {
    	if(x < 0) {x=-x,putchar('-');}
    	rg int top=0;
    	do {IO::buf[++top]=x%10+'0';} while(x/=10);
    	while(top) putchar(IO::buf[top--]);
    	if(pt) putchar(aft);
    }
    
    const int maxn = 100010;
    const int ccnt = 6;
    
    int n,q;
    int MU[maxn],belong[maxn],bk[maxn];
    int inv[8][maxn];
    
    struct Ask {
    	int l,r,num;
    	bool ans;
    	inline bool operator<(const Ask &_others) const {
    		if(belong[this->l] != belong[_others.l]) return this->l < _others.l;
    		if(belong[this->l] & 1) return this->r < _others.r;
    		else return this->r > _others.r;
    	}
    };
    Ask ask[maxn];
    
    inline bool cmp(const Ask &_a,const Ask &_b) {
    	return _a.num < _b.num;
    }
    
    struct C {
    	int mod;
    	int ans;
    	C(int _x=0) {mod=_x,ans=1;}
    };
    C CU[8];
    
    void GetInv(ci,ci);
    
    int main() {
    	freopen("1.in","r",stdin);
    	qr(n);qr(q);
    	for(rg int i=1;i<=n;++i) qr(MU[i]);
    	for(rg int i=1,sn=sqrt(n);i<=n;++i) belong[i]=i/sn;
    	for(rg int i=1;i<=q;++i) {
    		qr(ask[i].l);qr(ask[i].r);ask[i].num=i;
    	}
    	CU[1]=C(1000000007);CU[2]=C(1000000009);CU[3]=C(19260817);CU[4]=C(998244353);CU[5]=C(10000007);
    	for(int i=1;i<ccnt;++i) GetInv(CU[i].mod,i);
    	std::sort(ask+1,ask+1+q);
    	int prel=ask[1].l,prer=ask[1].l-1;
    #define jd(o) (bk[MU[o]] > 1)
    	for(rg int i=1;i<=q;++i) {
    		int l=ask[i].l,r=ask[i].r;
    		while(prel < l) {
    			if(jd(prel)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prel]]]%CU[j].mod;
    			}
    			--bk[MU[prel]];
    			if(jd(prel)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prel]]%CU[j].mod;
    			}
    			++prel;
    		}
    		while(prel > l) {
    			--prel;
    			if(jd(prel)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prel]]]%CU[j].mod;
    			}
    			++bk[MU[prel]];
    			if(jd(prel)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prel]]%CU[j].mod;
    			}
    		}
    		while(prer < r) {
    			++prer;
    			if(jd(prer)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prer]]]%CU[j].mod;
    			}
    			++bk[MU[prer]];
    			if((jd(prer))) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prer]]%CU[j].mod;
    			}
    		}
    		while(prer > r) {
    			if(jd(prer)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*inv[j][bk[MU[prer]]]%CU[j].mod;
    			}
    			--bk[MU[prer]];
    			if(jd(prer)) {
    				for(rg int j=1;j<ccnt;++j) CU[j].ans=1ll*CU[j].ans*bk[MU[prer]]%CU[j].mod;
    			}
    			--prer;
    		}
    		bool _ans=true;
    		for(rg int j=1;j<ccnt;++j) if(CU[j].ans != 1) {
    			_ans=false;break;
    		}
    		ask[i].ans=_ans;
    	}
    #undef jd
    	std::sort(ask+1,ask+1+q,cmp);
    	for(rg int i=1;i<=q;++i) 
    		if(ask[i].ans) puts("Yes");
    		else puts("No");
    	return 0;
    }
    
    void GetInv(ci mod,ci cur) {
    	inv[cur][1]=1;
    	for(rg int i=2;i<=n;++i) inv[cur][i]=1ll*(mod-mod/i)*inv[cur][mod%i]%mod;
    }
    

    Summary

    貌似这次没啥好summary的

  • 相关阅读:
    WAMP 2.2 配置与IIS共用单IP,多域名多网站配置方法
    [.NET MVC4 入门系列00]目录
    [.NET MVC4 入门系列04]Controller和View间交互原理
    [.NET MVC4 入门系列05]添加自定义查询页Search
    [.NET MVC4 入门系列02]MVC Movie 为项目添加Model
    [.NET MVC4 入门系列07] 在Model模型模块中添加验证
    [.NET MVC4 入门系列03]使用Controller访问Model中数据
    DateTime 类常用技巧
    Access 注意地方
    互联网公司老板的十大谎言,别对号入座
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10001439.html
Copyright © 2020-2023  润新知