• P6477 [NOI Online #2 提高组] 子序列问题


    先离散化。记 (A_i) 上一次出现的位置为 (last_{A_i}),如果第一次出现则 (last_{A_i}=0)

    考虑在末尾加入 (A_i) 产生的贡献,其实就是维护每个左端点和当前右端点形成的区间。对于 (f(1sim last_{A_i},i)),其值不变仍然是 (f(1sim last_{A_i},i-1))。对于 (f(last_{A_i}+1sim i,i)),其值加一。

    这样我们需要一个数据结构来实现区间加一和全局求平方和,拆一波式子:

    [(x+y)^2=x^2+2xy+y^2 ]

    用超级树状数组维护即可,另外记录下当前全局平方和,每次加上多出来的贡献。代码写得有点乱,注意 (y) 肯定是 (1)

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000005
    #define Mod 1000000007
    #define For(i,x,y)for(i=x;i<=(y);i++)
    #define lowbit(x)((x)&-(x))
    int c1[N],c2[N],a[N],b[N],last[N],n;
    int read()
    {
    	int A;
    	bool K;
    	char C;
    	C=A=K=0;
    	while(C<'0'||C>'9')K|=C=='-',C=getchar();
    	while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
    	return(K?-A:A);
    }
    int sum(int x)
    {
    	int ret=0,y=x;
    	while(x)ret=(ret+1LL*c1[x]*(y+1)-c2[x]+Mod)%Mod,x-=lowbit(x);
    	return ret;
    }
    void add(int x,int val)
    {
    	int y=x;
    	while(x<=n)
    	{
    		c1[x]=(c1[x]+val)%Mod;
    		c2[x]=(c2[x]+val*y+Mod)%Mod;
    		x+=lowbit(x);
    	}
    }
    int main()
    {
    	int i,m,ans,now;
    	ans=now=0;
    	n=read();
    	For(i,1,n)a[i]=b[i]=read();
    	sort(b+1,b+n+1);
    	m=unique(b+1,b+n+1)-b-1;
    	For(i,1,n)
    	{
    		a[i]=lower_bound(b+1,b+m+1,a[i])-b;
    		now=(1LL*now+i-last[a[i]]+((1LL*sum(i)-sum(last[a[i]])+Mod)<<1))%Mod;
    		add(last[a[i]]+1,1),add(i+1,-1);
    		last[a[i]]=i;
    		ans=(ans+now)%Mod;
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用
    MVC5+EF6 入门完整教程十
    MVC5+EF6 入门完整教程九
    MVC5+EF6 入门完整教程八
    MVC5+EF6 入门完整教程七
    MVC5+EF6 入门完整教程六
    MVC5+EF6 入门完整教程五
    MVC5+EF6 入门完整教程四
    MVC5 + EF6 完整入门教程三
    从前端的UI开始
  • 原文地址:https://www.cnblogs.com/May-2nd/p/14856256.html
Copyright © 2020-2023  润新知