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\n",a)

#define PRSF(a)        printf("%s\n",a)

#define PRFFU(a)        printf("%I64d\n",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\n");

	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



*/



 

 

 

你可能感兴趣的:(substring)