• Substrings 第37届ACM/ICPC 杭州赛区现场赛C题(hdu 4455)


    http://acm.hdu.edu.cn/showproblem.php?pid=4455

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4384

    题目大意就不多说了,官方的解法是dp,没太理解,自己想了一个直接点的方法,O(n)。

    既然要计算所有贡献和,对于区间长度为k,假设集合中的元素全都相同,那么这个元素将会贡献给所有长度为k 的子区间。而事实上,所有元素不可能相同,因此就不可能贡献给所有长度为k 的子区间,那么思考,那些子区间是无法贡献的。假设集合中有序列 1......1,如果两个1的间隔为s,那么对于(k<s)的情况,总共有s-k+1个区间是没法贡献的。

    而且,只要是任意的k<s,总存在区间是没法贡献的。对于一个k,

    s1-k

    s2-k
    。。。
    sum-k*cnt,记录s 的和,记录s>k的个数,就可以求出没法贡献的次数。再用总数减去就行了。有点抽象,能理解的理解理解。
    #include<algorithm>
    #include<iostream>
    #include<fstream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    #include<ctime>
    
    using namespace std;
    #define FOR(i,a,b)    for(int i=a;i<b;i++)
    #define FORD(i,a,b)    for(int i=a;i>b;i--)
    #define MST(a,num)    memset(a,num,sizeof(a))
    #define MCP(d,s)    memcpy(d,s,sizeof(s))
    #define WH(n)         while(scanf("%d", &n) != EOF)
    #define WHZ(n)         while(scanf("%d", &n) != EOF && n != 0)
    #define SCF(a)        scanf("%d",&a)
    #define PRF(a)        printf("%d",a)
    #define PRS(a)        printf("%s",a)
    #define PRFF(a)        printf("%d
    ",a)
    #define PRSF(a)        printf("%s
    ",a)
    #define PRFFU(a)        printf("%I64d
    ",a)
    
    #define PI acos(-1)
    #define max3(a,b,c)     max(max(a,b),c)
    #define max4(a,b,c,d)     max(max(a,b),max(c,d))
    
    #define FORE(e,x) for(__typeof(x.begin()) e=x.begin(); e!=x.end(); e++) //foreach(it, ans ) cout<<*it<<" ";
    #define all(a) (a).begin(),(a).end() //sort(all(v));
    #define len(a) ((int)(a).size())
    #define pb push_back
    #define mk make_pair
    #define V(etype) vector<etype>
    
    typedef __int64 Uint;
    typedef vector<int> Vint;
    typedef pair<int,int>mypair;
    
    #define INF 0x3f3f3f3f
    #define eps 1e-9
    #define N 1000000+10
    int q[N];
    int head[N];
    int rt[N];
    int cnt[N];
    int num[N];
    Uint sum[N];
    int main()
    {
    int n,a,m;
    
    //	freopen("data.in","r",stdin);
    //	freopen("data2.out","w",stdout);
    while((cin>>n)&&n){
    MST(cnt,0);
    MST(sum,0);
    MST(rt,-1);
    MST(head,-1);
    q[0]=0;
    FOR(i,0,n){
        SCF(num[i]);
        if(head[num[i]]==-1)q[++q[0]]=num[i];
        rt[i]=head[num[i]];
        head[num[i]]=i;
    }
    FOR(i,1,q[0]+1){
    rt[n]=head[q[i]];
        for(int j=n;j!=-1;j=rt[j]){
            cnt[j-rt[j]]--;
            sum[j-rt[j]]-=j-rt[j];
            cnt[0]++;
            sum[0]+=j-rt[j];
        }
    }
    FOR(i,1,n){
    sum[i]+=sum[i-1],cnt[i]+=cnt[i-1];
    //ret[i]=(n-i+1)*q[0]-(sum[i]-num[i]*cnt[i]);
    }
    Uint s1,s2;
    SCF(m);
    while(m--){
        SCF(a);
    	if(!a)PRSF("0
    ");
    	else{
        s1=(n-a+1);
        s1*=q[0];
        s2=a;
        s2*=cnt[a];
        s2=sum[a]-s2;
        PRFFU(s1-s2);
    	}
    }
    
    }
    return 0;
    }
    /*
    7
    1 1 2 3 4 4 5
    3
    1 2 3
    7
    1 1 2 3 4 4 5
    4
    1 2 3 0
    
    */
    


  • 相关阅读:
    通俗的讲解下傅立叶分析和小波分析之间的关系
    Kalman滤波
    K-L变换和 主成分分析PCA
    c语言字符串库函数#include<string.h>
    c语言字符类别测试库函数#include<ctype.h>
    c语言之extern关键字
    陈正冲老师讲c语言之声明和定义的区别
    陈正冲老师讲c语言之const关键字
    陈正冲老师讲c语言void关键字
    陈正冲老师讲c语言之内存的申请malloc() 和释放free()
  • 原文地址:https://www.cnblogs.com/riasky/p/3464843.html
Copyright © 2020-2023  润新知