zoukankan      html  css  js  c++  java
  • HDU7055 Yiwen with Sqc 推式子

    HDU7055 Yiwen with Sqc 推式子

    题意

    (sqc(s,i,j,c))表示字符串(s)中字符(c)在区间([l,r])出现次数

    [sum_{c=97}^{122}sum_{i=1}^nsum_{j=i}^n sqc(s,i,j,c)^2 ]

    [1 leq T leq 100\ |s| leq 10^5 ]

    分析

    题解的做法太巧妙 没有想到,万能的笨办法:枚举端点

    考虑对每个字符分别求和

    把字符串中等于当前位置的字符看成1,否则看成0,这样相当于求1的前缀和平方

    枚举左端点,我们就可以试图去维护这样的东西,因为1的贡献就是(sum i^2) 可以根据当前1的个数直接求,我们只需要维护0的贡献

    把连续的0分段,得到0的贡献就是(sum cnt[i]j^2)

    考虑左端点右移对0的贡献的影响就是(cnt[i]j^2 -> cnt[i](j-1)^2 = cnt[i]j^2 - cnt[i]2j + cnt[i])

    发现第一项不变,第二项可以继续维护,第三项可以预处理后缀和,第二项维护方法仍然类似,考虑左端点又移可能的影响(cnt[i]2j -> cnt[i]2(j-1) -> cnt[i]2j - cnt[i])

    这样就能够(O(1))维护了

    代码

    调试了很久,这类题一定要想清楚过程再写,否则一定是浪费机时

    #include<bits/stdc++.h>
    #define pii pair<ll,ll>
    #define fi first
    #define se second
    #define int long long
    using namespace std;
    typedef long long ll;
    
    inline ll rd(){
    	ll x;
    	scanf("%lld",&x);
    	return x;
    }
    
    
    const int maxn = 1e5 + 5;
    const int MOD = 998244353;
    
    inline int mul(int a,int b){
    	return (ll)a * b % MOD;
    }
    
    inline void add(int &a,int b){
    	a += b;
    	if(a >= MOD) a -= MOD;
    }
    
    inline int ksm(int a,int b = MOD - 2,int m = MOD){
    	int ans = 1;
    	int base = a;
    	while(b){
    		if(b & 1) ans = mul(ans,base);
    		base = mul(base,base);
    		b >>= 1;
    	}
    	return ans;
    }
    
    char s[maxn];
    int Get[maxn];
    
    
    int suf[maxn];
    int Suf[maxn];
    
    int main(){
    	//freopen("input.txt","r",stdin);
    	int T = rd();
    	for(int i = 1;i < maxn;i++){
    		Get[i] = Get[i - 1] + (ll)i * i % MOD;
    		if(Get[i] >= MOD) Get[i] -= MOD;
    	}
    	while(T--){
    		scanf("%s",s);
    		int n = strlen(s);
    		int ans = 0;
    		int mulsuf;
    		for(char ch = 'a';ch <= 'z';ch++){
    			for(int i = 0;i <= n + 1;i++)
    				suf[i] = Suf[i] = 0;
    			mulsuf = 0;
    			int cnt = 0;
    			int cnt_1 = 0;
    			for(int i = 0;i < n;i++)
    				if(s[i] != ch) suf[cnt]++;
    				else {
    					cnt_1++;
    					if(suf[cnt]) add(mulsuf,(ll)2 * suf[cnt++] * (cnt_1 - 1) % MOD); 
    				}
    			if(!suf[cnt]) cnt--;
    			if(s[n - 1] != ch) add(mulsuf,(ll)2 * suf[cnt] * (cnt_1) % MOD);
    			if(!cnt_1) continue;
    			Suf[cnt + 1] = 0;
    			for(int i = cnt;i >= 0;i--){
    				Suf[i] = Suf[i + 1] + suf[i];
    				if(Suf[i] >= MOD) Suf[i] -= MOD;
    			}
    			/*
    			if(ch == 'a') {
    				cout << cnt << '
    ';
    				for(int i = 0;i <= cnt;i++)
    					cout << suf[i] << ' ';
    				puts("");
    				for(int i = 0;i <= cnt;i++)
    					cout << Suf[i] << ' ';
    				puts("");
    			}*/
    			
    			/*
    			for(int i = st,j = 1;i <= cnt;i++,j++){
    				add(mulsuf,2 * j * suf[i]);
    			}*/
    			int lst = 0;
    			int sb = 0;
    			for(int i = 0;i < n;i++){
    				if(s[i] == ch) sb++;
    				add(lst,mul(sb,sb));
    			}
    			add(ans,lst);
    			int fro = !(s[0] == ch);
    			int Lst = lst - Get[cnt_1];
    			Lst = (Lst + MOD) % MOD;
    			
    			for(int i = 1;i < n;i++){
    				//if(ch == 'a') cout << i << ' ' << mulsuf << ' ' << lst << ' ' << Lst << '
    ';
    				if(s[i - 1] != ch) {
    					add(ans,lst);
    				}
    				else if(s[i - 1] == ch && s[i] == ch) {
    					cnt_1--;
    					lst = Get[cnt_1];
    					Lst -= mulsuf;
    					add(Lst,MOD);
    					add(Lst,Suf[fro]);
    					mulsuf -= (2 * Suf[fro]) % MOD;
    					add(mulsuf,MOD);
    					//add(Lst,Suf[fro]);
    					//fro++;
    					add(lst,Lst);
    					add(ans,lst);
    				}
    				else if(s[i - 1] == ch && s[i] != ch) {
    					cnt_1--;
    					lst = Get[cnt_1];
    					Lst -= mulsuf;
    					add(Lst,Suf[fro]);
    					add(Lst,MOD);
    					mulsuf -= (2 * Suf[fro]) % MOD;
    					add(mulsuf,MOD);
    					//add(Lst,Suf[fro]);
    					fro++;
    					add(lst,Lst);
    					add(ans,lst);
    				}
    			}
    			//cout << ans << '
    ';
    		}
    		printf("%d
    ",ans);
    	}
    }
    
    
    
    
  • 相关阅读:
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之六 多点触控
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之九 定位
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之七 重力感应
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之五 保存数据的几种方式
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之八 照相机
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之三 Application 配置详解
    Adobe Flash Builder 4.5 Android Air 程序开发系列 之四 打开与关闭应用程序是的保存数据
    ADOBE FLASH BUILDER 4.6 IOS 开发之部署与调试
    [译] 高性能JavaScript 1至5章总结
    页签及盒子的web标准实现
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15178078.html
Copyright © 2011-2022 走看看