返回顶部

Codeforces Global Round 4 B. WOW Factor (前缀和,数学)

  • 题意:找出序列中有多少子序列是\(wow\),但是\(w\)只能用\(vv\)来表示.

  • 题解:我们分别记录连续的\(v\)\(o\)的个数,用\(v1\)\(v2\)存,这里要注意前导\(o\)不能要,观察一下写出答案公式:\(ans=v1[i]*(v2[i]*(v1[i+1]+...+v1[k])+v2[i+1]*(v1[i+2]+...+v1[k])+...+v2[k-1]*v[k])+v1[i+1]*(...)+...+v1[k-1]*v2[k-1]*v1[k]\),很显然我们是不能直接算的,但是发现这个公式里面有很多连续的线性和,所以我们可以用前缀和来进行复杂度的优化,将其降到\(O(n)\).

  • 代码:

    string s;
    vector<ll> v1,v2;
    ll cnt1,cnt2;
    ll pre1[N],pre[N];
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>s;
        bool flag=false;
        for(int i=0;i<(int)s.size();++i){
        	if(s[i]=='v'){
        		cnt1++;
        		if(cnt2 && flag){
        			v2.pb(cnt2);
        			cnt2=0;
        		}
        		if(!flag) cnt2=0;
        		flag=true;
        	}
        	else{
        		cnt2++;
        		if(cnt1){
        			v1.pb(cnt1);
        			cnt1=0;
        		}
        	}
        }	
        if(cnt1) v1.pb(cnt1);
    
        int len1=(int) v1.size();
        int len2=(int) v2.size();
        for(int i=len1-1;i>=0;--i){
        	pre1[i]=pre1[i+1]+v1[i]-1;   //先对v1求前缀和.
        }	
        for(int i=len2-1;i>=0;--i){
        	pre[i]=pre[i+1]+v2[i]*pre1[i+1];  //求出v2[i]*(v1[i+1]+...+v1[k])的前缀和pre[i]<-这里(...)的就是我们上一步求的前缀和pre1[i+1].
        }
        ll ans=0;
        for(int i=0;i<len1;++i){
        	ans+=(v1[i]-1)*pre[i];
        }
        cout<<ans<<endl;
    	
        return 0;
    }
    
posted @ 2020-10-14 13:19  _Kolibri  阅读(124)  评论(0)    收藏  举报