c 【NOIP2017GDKOI模擬1.12】

這裏寫圖片描述
樣例輸入:
這裏寫圖片描述
100110100
5
11
101
010
10
00

樣例輸出:
這裏寫圖片描述
1
3
4
5
2

數據範圍:
這裏寫圖片描述


思路

比賽時沒有注意到所有詢問串的長度總和不超過二十萬這個條件,然後就只想到暴力。。。。


解法

1.據說有根號級別的解法?%%%%
2.由於詢問串的長度總共不超過二十萬,那麼複雜度會遠小於理論複雜度。。。。。
我們先把一部分答案存下來(這裏我存了長度300的,300~400應該都行)。
設f[i][j]表示字符串長度爲i的區間1的個數有j個的數量,預處理出來。
對於每一個詢問,如果詢問串的長度<=300,直接輸出即可。大於就暴力。
事實證明,跑的似乎比根號的要快。。。。


代碼

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

const int maxn=305,len=2*1e5+5;
int f[maxn][maxn],q,ans,sum[len];
char ch[len],c;

int main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    scanf("%s",ch+1);
    int tot=strlen(ch+1);
    fo(i,1,tot) {
        sum[i]=sum[i-1];
        if (ch[i]=='1') ++sum[i];
        int pre=max(i-300,1);
        fo(j,pre,i) f[i-j+1][sum[i]-sum[j-1]]++;
    }
    scanf("%d",&q);
    fo(o,1,q){
        ans=0;
        int lenn=0,num=0;
        c=getchar();
        while (c!='0'&&c!='1') c=getchar();
        while (c=='1'||c=='0'){
            ++lenn;
            if (c=='1') ++num;
            c=getchar();
        }
        if (lenn<=300) printf("%d\n",f[lenn][num]);
        else {
            fo(i,lenn,tot)
            if (sum[i]-sum[i-lenn]==num) ++ans;
            printf("%lld\n",ans);
        }
    }
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章