cf1527 c Sequence Pair Weight
生活随笔
收集整理的這篇文章主要介紹了
cf1527 c Sequence Pair Weight
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Problem - C - Codeforces
題目大意:給定一串序列,求出它所有子序列的貢獻度之和
貢獻度:某個字串{1,1,2,2,1}中相同數字的對數{i,j}(i<j,下同)
即{1,2} {3,4} {1,5} {2,5},貢獻度為4
在t了十幾發之后終于切了這題
題解來了:
找出一對{a[i],a[j]},則包含i……j的子串都能被這對{a[i],a[j]}所貢獻,i前面有i-1個數字,j后面有n-j個數字,組合起來一共有i*(n-j+1)種情況是包含i……j的子串,這些字串都能提供一個貢獻值
暴力:雙層for求出每對{a[i],a[j]}的貢獻值,求和
然后第一個T就來了
那在進行優化
我們得到了i*(n-j+1)這個式子,那么當j不變的時候,存在一個或多個i符合條件,則j在后面的所有貢獻值為(i1+i2+……)*(n-j+1)
所以我們考慮用前綴和來維護,將j從后往前搜索,搜到后把前綴和-j然后找下一個j
前綴和要記錄a[j],可是a[j]<=1e9,明顯數組會爆
但是我們高興的發現n只有1e5,這時候我們可以考慮離散化,大于1e5的最小質數是100003,自己創建一種規則來把這些數字塞到數組里
我們考慮建一個二維數組,第一排記離散化前的數字,第二排記前綴和
思路大致就完成了
下面是代碼
#include<bits/stdc++.h> using namespace std; long long t[100005],k[100010][3];//t存序列,k是離散化 int main() {std::ios::sync_with_stdio(false);cin.tie(NULL);long long n,a,i,z,y;cin>>n;while(n--){cin>>a;if(a==2){for(i=1;i<=a;i++) {cin>>t[i];}if(t[1]==t[2]) cout<<1<<"\n";else cout<<0<<"\n";continue;}if(a==1) {cin>>t[1];cout<<0<<"\n";continue;}memset(k,0,sizeof(k));memset(t,0,sizeof(t));y=0;for(i=1;i<=a;i++) {z=0;cin>>t[i];if(t[i]<100003){while(k[(t[i]+z)%100003][1]!=t[i]&&k[(t[i]+z)%100003][1]!=0)//離散化{z++; }k[(t[i]+z)%100003][1]=t[i];k[(t[i]+z)%100003][2]+=i;}else{while(k[(t[i]%100003+z)%100003][1]!=t[i]&&k[(t[i]%100003+z)%100003][1]!=0){z++;}k[(t[i]%100003+z)%100003][1]=t[i];k[(t[i]%100003+z)%100003][2]+=i;//前綴和}//離散化}for(i=a;i>=2;i--){z=0;while(k[(t[i]%100003+z)%100003][1]!=t[i]){z++;}if(k[(t[i]%100003+z)%100003][1]!=0&&k[(t[i]%100003+z)%100003][2]!=i){y+= (k[(t[i]%100003+z)%100003][2]-i)*(a-i+1);k[(t[i]%100003+z)%100003][2]=k[(t[i]%100003+z)%100003][2]-i; }}cout<<y<<"\n";} }?
?
總結
以上是生活随笔為你收集整理的cf1527 c Sequence Pair Weight的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解C语言中两级指针(char **
- 下一篇: VS2017 如何连接mysql数据库依