HDU 6058 2017 Multi-University Training Contest - Team 3 1003 :Kanade's sum:简单计数问题
2017-08-02 14:01
579 查看
题意:给定一个n(<=5e5)的全排列,以及一个 K 。定义value(l , r , k)=区间[ l , r ]中第 k 大的元素,如果区间长度 len = r - l + 1 < k 则 value( l , r , k ) = 0 求所有子序列的value( k )之和。
题解:又是一道计数题,那么这个题一个比较好的思路是:枚举全排列中的每一个 a[ i ],让他作为value的答案,求出这样的序列有num个,那么a[ i ] 贡献的答案就是a[ i ] * num。num的求法可以分类讨论:让左边有x个比a[ i ]大的数字,右边有k-1-x个。那么我们需要枚举每一个a[ i ]这就有了n的复杂度。那么我们必须对于给定的a[ i ],快速地求出左右分别最多k个比他大的数字的下标。比他大的数字!那么我们就排个序吧,从小到大的来计算a[ i ]的贡献,那么所有没考虑的的数字都是比a[
i ]大的。可以用一个类似链表的东西维护每一个i位置的pre和nxt位置,这个指针是a[ i ]意义下的,意思是只要pre[ x ]是x左边第一个比a[ i ]大的数字的位置,而不是和a[ x ]比较。所以初始化为pre[ i ] = i-1,nxt[ i ] = i+1,因为初始是在0意义下的。考虑完1这个数字之后,要把 nxt[ pre[ 1 ] ] = nxt [ 1 ] 且 pre[ nxt[ i ] ] = pre[ i ],相当于把 i 从双向链表删除掉。
当然还有对应的从大到小来考虑的思路:每次用插排的方法,把新的值=i 的下标插入到已有的下标序列,那么对于数字 i-1 来说,这些下标就是比我大的所有的数字的下标,然后可以在这个有序序列中用lower_bound查一下 i-1的下标,从而分出左右,然后相同的分别向两边取 k 个,统计答案,但是。。。如果使用vector不知道为什么常数巨大orz。。。自己造的双向链表应该可以不TLE的。
文末有更多计数问题的题解传送门。本博客里有更多,请自行寻找(因为我不会回头维护之前的博客的。orz)
Code:
题解:又是一道计数题,那么这个题一个比较好的思路是:枚举全排列中的每一个 a[ i ],让他作为value的答案,求出这样的序列有num个,那么a[ i ] 贡献的答案就是a[ i ] * num。num的求法可以分类讨论:让左边有x个比a[ i ]大的数字,右边有k-1-x个。那么我们需要枚举每一个a[ i ]这就有了n的复杂度。那么我们必须对于给定的a[ i ],快速地求出左右分别最多k个比他大的数字的下标。比他大的数字!那么我们就排个序吧,从小到大的来计算a[ i ]的贡献,那么所有没考虑的的数字都是比a[
i ]大的。可以用一个类似链表的东西维护每一个i位置的pre和nxt位置,这个指针是a[ i ]意义下的,意思是只要pre[ x ]是x左边第一个比a[ i ]大的数字的位置,而不是和a[ x ]比较。所以初始化为pre[ i ] = i-1,nxt[ i ] = i+1,因为初始是在0意义下的。考虑完1这个数字之后,要把 nxt[ pre[ 1 ] ] = nxt [ 1 ] 且 pre[ nxt[ i ] ] = pre[ i ],相当于把 i 从双向链表删除掉。
当然还有对应的从大到小来考虑的思路:每次用插排的方法,把新的值=i 的下标插入到已有的下标序列,那么对于数字 i-1 来说,这些下标就是比我大的所有的数字的下标,然后可以在这个有序序列中用lower_bound查一下 i-1的下标,从而分出左右,然后相同的分别向两边取 k 个,统计答案,但是。。。如果使用vector不知道为什么常数巨大orz。。。自己造的双向链表应该可以不TLE的。
文末有更多计数问题的题解传送门。本博客里有更多,请自行寻找(因为我不会回头维护之前的博客的。orz)
Code:
#include<bits/stdc++.h> using namespace std; const int MAX = 500050; int pre[MAX],nxt[MAX]; int index[MAX]; int n,k,t; inline int read(){ char ch = getchar(); int re = 0; while (ch>='0'&&ch<='9'){ re = re*10+ch-'0'; ch = getchar(); } return re; } inline void input(){ n = read(); k = read(); for (int i = 1;i<=n;i++){ index[read()] = i; } } inline void init(){ for (int i = 0;i<=n+1;i++){ pre[i]= i-1; nxt[i]= i+1; } // ans = 0; } void erase(int kk){ int pp = pre[kk]; int nn = nxt[kk]; if (pp) nxt[pp] = nn; if (nn<n+1) pre[nn] = pp; pre[kk]=nxt[kk] = 0; } long long ans; const int MAXK = 85; int lans[MAXK],rans[MAXK]; void print(){ cout<<"INFO"<<endl; for (int i = 0;i<=k;i++){ cout<<"L["<<i<<"]="<<lans[i]<<endl; } for (int i = 0;i<=k;i++){ cout<<"R["<<i<<"]="<<rans[i]<<endl; } cout<<"ANS:"<<ans<<endl; cout<<"INFO END"<<endl; } inline void work(){ ans = 0; for (int i = 1;i<=n-k+1;i++){ int l = 0,r = 0; int p = index[i]; memset(lans,0,sizeof(lans)); memset(rans,0,sizeof(rans)); for (int ii = p;ii>=0&&l<=k;ii=pre[ii]){ lans[l++] = ii; } for (int ii = p;ii<=n+1&&r<=k;ii = nxt[ii]){ rans[r++]= ii; } lans[l] = 0; rans[r] = n+1; for (;l>=1;l--){ if (k-l+1<=r&&k-l>=0){ ans += 1LL*i*(lans[l-1]-lans[l])*(rans[k-l+1]-rans[k-l]); // cout<<l-1<<" "<<k-l<<" "<<ans<<endl; } } // print(); erase(p); } printf("%I64d\n",ans); } int main(){ while (t--){ input(); // cout<<"INPUT"<<n<<" "<<k<<endl; init(); work(); } return 0; }
相关文章推荐
- 2017 Multi-University Training Contest - Team 3 1003(hdu 6058) Kanade's sum(链表)(set)
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- HDU-6058 Kanade's sum - 2017 Multi-University Training Contest - Team 3(思维+模拟链表)
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- 2017 Multi-University Training Contest - Team 3 1003 Kanade's sum
- 2017 Multi-University Training Contest - Team 3 1003 Kanade's sum
- HDU 3065 2017 Multi-University Training Contest - Team 1 1003 Corlorful Tree:计数+树上分块