zoukankan      html  css  js  c++  java
  • HDU 6058 Kanade's sum(链表)

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

    题意:
    找出所有区间第K大的值之和。

    思路:

    又有点贡献值的味道,就是考虑当前这个数贡献了几个区间。

    然后往左和往右分别找大于当前数的k-1个数,这样就可以确定区间的个数,这要求我们从小到大找 并且找完之后需要删除这个数,用链表来维护。

    删除元素的目的是为了加速,保证了当前查找的元素是最小值,所以只需要跳跃寻找k次就可以。具体看代码。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<sstream>
     6 #include<vector>
     7 #include<stack>
     8 #include<queue>
     9 #include<cmath>
    10 #include<map>
    11 #include<set>
    12 using namespace std;
    13 typedef long long ll;
    14 typedef pair<int,int> pll;
    15 const int INF = 0x3f3f3f3f;
    16 const int maxn = 5*1e5 + 5;
    17 
    18 int n, k;
    19 
    20 int a[maxn];
    21 int pre[maxn];
    22 int nxt[maxn];
    23 int pos[maxn];
    24 
    25 int before[maxn];
    26 int after[maxn];
    27 
    28 ll solve(int p)
    29 {
    30     int c1=0,c2=0;
    31     for(int i=p; i&&c1<=k; i=pre[i])
    32     {
    33         before[c1++]=i-pre[i];  //左边i个比当前数大的方法数
    34     }
    35     for(int i=p; i<=n&&c2<=k; i=nxt[i])
    36     {
    37         after[c2++]=nxt[i]-i;
    38     }
    39 
    40     ll ans=0;
    41     for(int i=0;i<c1;i++)  //左边i个,右边k-i+1个
    42     {
    43         if(k-i-1<c2)
    44         {
    45             ans+=before[i]*after[k-i-1];
    46         }
    47     }
    48 
    49     pre[nxt[p]]=pre[p];
    50     nxt[pre[p]]=nxt[p];
    51 
    52     return ans;
    53 }
    54 
    55 int main()
    56 {
    57     //freopen("in.txt","r",stdin);
    58     int T;
    59     scanf("%d",&T);
    60     while(T--)
    61     {
    62         scanf("%d%d",&n,&k);
    63         for(int i=1;i<=n;i++)
    64         {
    65             scanf("%d",&a[i]);
    66             pos[a[i]]=i;
    67         }
    68         for(int i=1;i<=n;i++)
    69         {
    70             pre[i]=i-1;
    71             nxt[i]=i+1;
    72         }
    73         pre[0]=0; nxt[n+1]=n+1;
    74 
    75         ll ans=0;
    76         for(int i=1;i<=n;i++)
    77         {
    78             ans+=solve(pos[i])*i;
    79         }
    80         printf("%lld
    ",ans);
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    [luogu T71973]卡常者π酱
    [日常] HEOI 2019 退役记
    [教程]网络流详解: 从入门到放弃
    [LOJ 6213]「美团 CodeM 决赛」radar
    [BZOJ 1568][JSOI2008]Blue Mary开公司
    [BZOJ 3167][HEOI 2013]SAO
    [BZOJ 4763]雪辉
    [LOJ 2146][BZOJ 4873][Shoi2017]寿司餐厅
    [HZNOI #koishi] Magic
    [luogu P4230]连环病原体
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7272993.html
Copyright © 2011-2022 走看看