Substrings(hdu 4455)

题意:

给定一个序列ai,个数为n。再给出一系列w;对于每个w,求序列中,所有长度为w的连续子串中的权值和,子串权值为子串中不同数的个数。

/*
    dp[i]表示长度为i的序列不同元素个数之和。
    考虑从i-1向i转移的时候,最后i-1个元素的贡献会消失,记last[i]表示最后i个元素中不重复元素的个数,则转移时,它的贡献是-last[i]。
    同时每个序列会多出a[i],a[i+1],a[i+2]等元素,这些元素对答案有贡献的前提是与前i-1个元素不重复。
    那么i这个元素对答案有贡献的范围是pos[a[i]]-i+1~i+1(pos[i]表示i前面的元素是a[i]的位置),用树状数组累加一下。
    所以转移方程为dp[i]=dp[i-1]+n-i+1-query(i)-last[i-1]
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1000010
#define lon long long
using namespace std;
int a[N],pos[N],c[N],last[N],n,m;
lon dp[N];
void updata(int x,int val){
    while(x<=n){
        c[x]+=val;
        x+=x&(-x);
    }
}
int query(int x){
    int tot=0;
    while(x){
        tot+=c[x];
        x-=x&(-x);
    }
    return tot;
}
int main(){
    while(1){
        scanf("%d",&n);
        if(!n) break;
        memset(pos,-1,sizeof(pos));
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            if(pos[a[i]]!=-1){
                updata(i-pos[a[i]]+1,1);
                updata(i+1,-1);
            }
            pos[a[i]]=i;
        }
        memset(pos,-1,sizeof(pos));
        memset(last,0,sizeof(last));
        for(int i=n;i;i--){
            last[n-i+1]=last[n-i];
            if(pos[a[i]]==-1) last[n-i+1]++;
            pos[a[i]]=i;
        }
        dp[1]=n;
        for(int i=2;i<=n;i++)
            dp[i]=dp[i-1]+(n-i+1-query(i))-last[i-1];
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int x;scanf("%d",&x);
            printf("%I64d\n",dp[x]);
        }
    }
    return 0;
}
时间: 2024-08-12 23:43:50

Substrings(hdu 4455)的相关文章

Valentine&#39;s Day Round 1001.Ferries Wheel(hdu 5174)解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5174 题目意思:给出 n 个人坐的缆车值,假设有 k 个缆车,缆车值 A[i] 需要满足:A[i−1]<A[i]<A[i+1](1<i<K).现在要求的是,有多少人满足,(他坐的缆车的值 + 他左边缆车的值) % INT_MAX == 他右边缆车的值. 首先好感谢出题者的样例三,否则真的会坑下不少人.即同一部缆车可以坐多个人.由于缆车的值是唯一的,所以可以通过排序先排出缆车的位置.求出

最短路 (HDU 2544)

最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 28836    Accepted Submission(s): 12480 Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找

BestCoder Round #70 Jam&#39;s math problem(hdu 5615)

Problem Description Jam has a math problem. He just learned factorization. He is trying to factorize ax^2+bx+cax?2??+bx+c into the form of pqx^2+(qk+mp)x+km=(px+k)(qx+m)pqx?2??+(qk+mp)x+km=(px+k)(qx+m). He could only solve the problem in which p,q,m,

RPG的错排 (HDU 2068)

RPG的错排 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6746    Accepted Submission(s): 2738 Problem Description 今年暑假杭电ACM集训队第一次组成女生队,其中有一队叫RPG,但做为集训队成员之一的野骆驼竟然不知道RPG三个人具体是谁谁.RPG给他机会让他猜猜,第一次猜:R是

BestCoder Round #29 1003 (hdu 5172) GTY&#39;s gay friends [线段树 判不同 预处理 好题]

传送门 GTY's gay friends Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 264    Accepted Submission(s): 57 Problem Description GTY has n gay friends. To manage them conveniently, every morning he o

字典树 Trie (HDU 1671)

Problem Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers: 1. Emergency 911 2. Alice 97 625 999 3. Bob 91 12 54 26 In this

SPOJ 694、705 Distinct Substrings 、 New Distinct Substrings (后缀数组)

题目大意: 求串中不同的子串的个数. 思路分析: 子串一定是某一个后缀的前缀. 所以我们把每一个后缀拿出来,分析它有多少个前缀,然后除去它与sa数组中前面那个后缀相同的前缀. 最后也就是 ans = segma (n-sa[i] + height[i]).... #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 1000005

BestCoder Round #1 1002 项目管理 (HDU 4858)

项目管理 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 738    Accepted Submission(s): 260 Problem Description 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的!两个节点间可能有多条边,不过一条边的两端必然是不同的节点.每个节点都有一个能量值. 现在我

【SPOJ】Distinct Substrings(后缀自动机)

[SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/endpos\)集合的大小 但是实际上我们没有任何必要减去不合法的数量 我们只需要累加每个节点表示的合法子串的数量即可 这个值等于\(longest-shortest+1=longest-parent.longest\) #include<iostream> #include<cstdio&g