• [莫队算法 线段树 斐波那契 暴力] Codeforces 633H Fibonacci-ish II



    题目大意:给出一个长度为n的数列a。

    对于一个询问lj和rj。将a[lj]到a[rj]从小到大排序后并去重。设得到的新数列为b,长度为k,求F1*b1+F2*b2+F3*b3+...+Fk*bk。当中F为斐波那契数列。F1=F2=1。对每一个询问输出答案模m。


    区间查询离线 用莫队算法

    开棵权值线段树,然后用斐波那契的性质update

    F(n+m)=F(n+1)*F(m)+F(n)*F(m-1);



    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    inline char nc()
    {
    	static char buf[100000],*p1=buf,*p2=buf;
    	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
    	return *p1++;
    }
    
    inline void read(int &x)
    {
    	char c=nc(),b=1;
    	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
    	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
    }
    
    int P;
    int sx[30005];
    int icnt;
    
    inline int Bin(int x){
    	return lower_bound(sx+1,sx+icnt+1,x)-sx;
    }
    
    struct SEGTREE{
    	struct node{
    		int k;
    		int fk,fk_1;
    		int a1,a2;
    		friend node operator + (node &A,node &B){
    			if (!A.k) return B;
    			if (!B.k) return A;
    			node ret;
    			ret.k=A.k+B.k;
    			(ret.fk=(A.fk+A.fk_1)*B.fk+A.fk*B.fk_1)%=P;
    			(ret.fk_1=A.fk*B.fk+A.fk_1*B.fk_1)%=P;
    			ret.a1=A.a1;
    			(ret.a1+=A.fk*B.a2+A.fk_1*B.a1)%=P;
    			ret.a2=A.a2;
    			(ret.a2+=(A.fk+A.fk_1)*B.a2+A.fk*B.a1)%=P;
    			return ret;
    		}
    	};
    	node T[120005];
    	int cnt[120005];
    	int M,TH;
    	inline void Build(int n){
    		for (M=1,TH=0;M<n+2;M<<=1,TH++);
    	}
    	inline int Query(){
    		return T[1].a1;
    	}
    	inline void Change(int s,int r){
    		s+=M;
    		if (r==1)
    		{
    			cnt[s]++;
    			if (cnt[s]==1)
    			{
    				T[s].k=1;
    				T[s].fk=1;
    				T[s].fk_1=0;
    				(T[s].a1=sx[s-M])%=P;
    				(T[s].a2=sx[s-M])%=P;
    				while (s>>=1)
    					T[s]=T[s<<1]+T[s<<1|1];
    			}
    		}
    		else if (r==-1)
    		{
    			cnt[s]--;
    			if (cnt[s]==0)
    			{
    				T[s].k=0;
    				T[s].fk=0;
    				T[s].fk_1=0;
    				T[s].a1=0;
    				T[s].a2=0;
    				while (s>>=1)
    					T[s]=T[s<<1]+T[s<<1|1];
    			}
    		}
    	}
    }SEG;
    
    int n,Q,B;
    int a[30005],ans[30005];
    
    struct event{
    	int x,y,lpos;
    	int idx;
    	bool operator < (const event &B) const{
    		return lpos==B.lpos?y<B.y:lpos<B.lpos;
    	}
    }eve[30005];
    
    inline void Mos()
    {
    	int l=1,r=0;
    	for (int i=1;i<=Q;i++)
    	{
    		while (r<eve[i].y) SEG.Change(Bin(a[++r]),1);
    		while (r>eve[i].y) SEG.Change(Bin(a[r--]),-1);
    		while (l<eve[i].x) SEG.Change(Bin(a[l++]),-1);
    		while (l>eve[i].x) SEG.Change(Bin(a[--l]),1);
    		ans[eve[i].idx]=SEG.Query();
    	}
    }
    
    int main()
    {
    	freopen("t.in","r",stdin);
    	freopen("t.out","w",stdout);
    	read(n); read(P); B=sqrt(n);
    	for (int i=1;i<=n;i++)
    		read(a[i]),sx[++icnt]=a[i];
    	sort(sx+1,sx+icnt+1);
    	icnt=unique(sx+1,sx+icnt+1)-sx-1;
    	SEG.Build(icnt);
    	read(Q);
    	for (int i=1;i<=Q;i++)
    	{
    		read(eve[i].x); read(eve[i].y);
    		eve[i].lpos=(eve[i].x-1)/B+1; eve[i].idx=i;
    	}
    	sort(eve+1,eve+Q+1);
    	Mos();
    	for (int i=1;i<=Q;i++)
    		printf("%d
    ",ans[i]);
    	return 0;
    }

    然而出题人太奇妙,这样的做法常数极大,还是暴力短小精悍


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 3e4+5;
    pair<int,int> a[maxn];
    int ans[maxn],step[maxn],f[maxn],l[maxn],r[maxn],last[maxn];
    
    int main()
    {
    	freopen("t.in","r",stdin);
    	freopen("t1.out","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i].first),a[i].second=i;
        sort(a+1,a+1+n);
        f[0]=1,f[1]=1;
        for(int i=2;i<=n;i++)
            f[i]=(f[i-1]+f[i-2])%m;
        int q;scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&l[i],&r[i]);
            last[i]=-1;
        }
        for(int i=1;i<=n;i++)
        {
            int d = a[i].first % m;
            for(int j=1;j<=q;j++)
            {
                if(a[i].second<l[j]||a[i].second>r[j])continue;
                if(a[i].first==last[j])continue;
                ans[j]=(ans[j]+f[step[j]++]*d)%m;
                last[j]=a[i].first;
            }
        }
        for(int i=1;i<=q;i++)
            printf("%d
    ",ans[i]);
    }



  • 相关阅读:
    数据库基础+重置root密码
    Bug定级
    测试用例和测试方法
    测试基础
    HDOJ-1010 Tempter of the Bone(dfs)
    POJ
    HDU-2089 不要62 (数位DP)
    Happy!
    LOJ-1422 万圣节服装
    数字三角形(数塔问题)
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7279076.html
Copyright © 2020-2023  润新知