• hdu 4455 dp


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

    去了几个头文件,然后终于A了

    以样例为例说明:
    1 1 2 3 4 4 5;
    明显dp[1]=n=7;
    长度为1的时候有7个区间。从长度为1到长度为2,就是把前6个区间往后增加一个数,把最后一个区间去掉。
    增加的6个数要看在该区间是否出现过,只要看它上一个相等的元素距离是否大于2
    所以dp[2]=dp[1]-1+4;
    以此类推就可以得出所以的dp值了。
    dp[i]=dp[i-1]-A+B;
    减的A是最后一个长度为i-1的区间的不同数的个数,这个很容易预处理得出来。
    加的B是第t个数到它上一个数的距离大于i-1的个数.
    这个B值也容易得出。
    用s[i]表示离上一个数的距离为i的个数,不断减掉就得到B了。
     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 #define ts printf("*****
    ");
     5 #define cl(a) memset(a,0,sizeof(a))
     6 const int maxn=1000007;
     7 long long dp[maxn];
     8 int dis[maxn]; //第i个数和前面最近相同的数的距离 例如1,2,1    d[3]=2
     9 int r[maxn]; //和前面最近相同的数的距离为i的个数
    10 int vis[maxn];
    11 int lastp[maxn]; //数i的最近上一个位置
    12 int a[maxn];
    13 int dif[maxn]; //从n-i+1到n不同的数的个数
    14 
    15 int main()
    16 {
    17     int i,j,k;
    18     #ifndef ONLINE_JUDGE
    19     freopen("1.in","r",stdin);
    20     #endif
    21     int n;
    22     while(scanf("%d",&n)!=EOF)
    23     {
    24         if(n==0)    break;
    25         cl(lastp);
    26         for(i=1;i<=n;i++)
    27         {
    28             scanf("%d",a+i);
    29             dis[i]=i-lastp[a[i]];
    30             lastp[a[i]]=i;
    31         }
    32         cl(r);
    33         for(i=1;i<=n;i++)
    34         {
    35             r[dis[i]]++;
    36         }
    37         cl(dif);
    38         cl(vis);
    39         int t=0;
    40         for(i=n;i>0;i--)
    41         {
    42             if(!vis[a[i]])
    43             {
    44                 vis[a[i]]=1;
    45                 t++;
    46             }
    47             dif[n-i+1]=t;
    48         }
    49         int sum=n;
    50         cl(dp);
    51         dp[1]=n;
    52         for(i=2;i<=n;i++)
    53         {
    54             dp[i]+=dp[i-1]-dif[i-1];//减掉最后一个区间的种类数
    55             sum-=r[i-1];
    56             dp[i]+=sum;
    57         }
    58         int q,tt;
    59         scanf("%d",&q);
    60         while(q--)
    61         {
    62             scanf("%d",&tt);
    63             printf("%I64d
    ",dp[tt]);
    64         }
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    Autofac
    MYSQL存储过程获取记录总数
    MYSQL通用存储过程
    判断用户用手机访问还是用电脑访问网页
    HttpRuntime.Cache与HttpContext.Current.Cache
    Eclipse之NDK编译-- Type 'jint' could not be resolved, and JNIEnv, jclass错误解决办法
    解决Android adjustresize全屏无效问题
    Android手机使用广播监听手机收到的短信
    使用Jackson解析首字母大写的json字符串
    Android Studio中设置提示函数用法
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4470416.html
Copyright © 2020-2023  润新知