2022NOIPA层联测4

正手一个[南猪入侵],反手一个[万箭齐发],我的[桃]真的快用完了……OI啊(MP),我(ZP)劝你出手前考虑一下,如果我DEAD了,你可就没牌了……话说难道我没有跳过忠吗??

 

问题 A: 【2022NOIP联测4 10月6日】字符串还原

string用熟了,于是就忘了它的时间复杂度,TLE 40 不过用起来是真的简单,10分钟不到就搞定了。

#include <bits/stdc++.h>

using namespace std;

int n, mid, flag;
string ans, u;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    n = read(); mid = n/2;
    cin >> u;
    for(int i=1; i<n-1; i++)
    {
        string t = u.substr(0, i) + u.substr(i+1);
        string s1 = t.substr(0, mid), s2 = t.substr(mid);
        if(s1 == s2)
        {
            if(!flag) {ans = s1; flag++;}
            else flag++;
        }
    }
    string t = u.substr(1);
    string s1 = t.substr(0, mid), s2 = t.substr(mid);
    if(s1 == s2)
    {
        if(!flag) {ans = s1; flag++;}
        else flag++;
    }
    t.clear(); s1.clear(); s2.clear();
    t = u.substr(0, n-1);
    s1 = t.substr(0, mid); s2 = t.substr(mid);
    if(s1 == s2)
    {
        if(!flag) {ans = s1; flag++;}
        else flag++;
    }
    if(flag > 1) printf("NOT UNIQUE\n");
    else if(!flag) printf("NOT POSSIBLE\n");
    else cout << ans << endl;

    return 0;
}
View Code

于是开始改hash,套用原来的string,TLE 95是因为每次答案的hash值我居然又拿出个string计算了一下。

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ll;
const int maxn = 2e6 + 30;

int n, mid, flag;
//ll mod = 1234567891;
ll f[maxn], m[maxn], B = 131, lstans, nowans;
string ans, u;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    n = read(); mid = n/2;
    cin >> u;
    m[0] = 1;
    for(int i=1; i<=n; i++) m[i] = m[i-1] * B;
    n = u.length();
    f[0] = u[0] - 'A' + 1;
    for(int i=1; i<n; i++)
    {
        f[i] = f[i-1] * B + (u[i]-'A'+1);
    }
    for(int i=1; i<=mid; i++)
    {
        ll h1 = f[i-1]*m[mid-i]+f[mid]-f[i]*m[mid-i];
        ll h2 = f[n-1]-f[mid]*m[n-mid-1];
        if(h1 == h2)
        {
            if(!flag)
            {
                string t = u.substr(0, i) + u.substr(i+1);
                string s1 = t.substr(0, mid), s2 = t.substr(mid);
                ans = s1; flag++;
                for(int i=0; i<ans.length(); i++)
                {
                    lstans = lstans * B + (ans[i]-'A'+1);
                }
            }
            else 
            {
                string t = u.substr(0, i) + u.substr(i+1);
                string s1 = t.substr(0, mid), s2 = t.substr(mid);
                nowans = 0;
                for(int i=0; i<s1.length(); i++)
                {
                    nowans = nowans * B + (s1[i]-'A'+1);
                }
                if(nowans == lstans) continue;
                else 
                {
                    printf("NOT UNIQUE\n"); exit(0);
                }
            }
        }
    }
    for(int i=mid+1; i<n-1; i++)
    {
        ll h1 = f[mid-1];
        ll h2 = f[n-1]-f[i]*m[n-i-1]+(f[i-1]-f[mid-1]*m[i-mid])*m[n-i-1];
        if(h1 == h2)
        {
            if(!flag)
            {
                string t = u.substr(0, i) + u.substr(i+1);
                string s1 = t.substr(0, mid), s2 = t.substr(mid);
                ans = s1; flag++;
                for(int i=0; i<ans.length(); i++)
                {
                    lstans = lstans * B + (ans[i]-'A'+1);
                }
            }
            else 
            {
                string t = u.substr(0, i) + u.substr(i+1);
                string s1 = t.substr(0, mid), s2 = t.substr(mid);
                nowans = 0;
                for(int i=0; i<s1.length(); i++)
                {
                    nowans = nowans * B + (s1[i]-'A'+1);
                }
                if(nowans == lstans) continue;
                else 
                {
                    printf("NOT UNIQUE\n"); exit(0);
                }
            }
        }
    }
    ll h1 = f[mid]-f[0]*m[mid], h2 = f[n-1]-f[mid]*m[mid];
    if(h1 == h2)
    {
        if(!flag) 
        {
            string t = u.substr(1);
            string s1 = t.substr(0, mid), s2 = t.substr(mid);
            ans = s1; flag++;
            for(int i=0; i<ans.length(); i++)
            {
                lstans = lstans * B + (ans[i]-'A'+1);
            }
        }
        else
        {
            string t = u.substr(1);
            string s1 = t.substr(0, mid), s2 = t.substr(mid);
            nowans = 0;
            for(int i=0; i<s1.length(); i++)
            {
                nowans = nowans * B + (s1[i]-'A'+1);
            }
            if(nowans != lstans)
            {
                printf("NOT UNIQUE\n"); exit(0);
            }
        }
    }
    h1 = f[mid-1]; h2 = f[n-2]-f[mid-1]*m[mid];
    if(h1 == h2)
    {
        if(!flag) 
        {
            string t = u.substr(0, n-1);
            string s1 = t.substr(0, mid), s2 = t.substr(mid);
            ans = s1; flag++;
            for(int i=0; i<ans.length(); i++)
            {
                lstans = lstans * B + (ans[i]-'A'+1);
            }
        }
        else 
        {
            string t = u.substr(0, n-1);
            string s1 = t.substr(0, mid), s2 = t.substr(mid);
            nowans = 0;
            for(int i=0; i<s1.length(); i++)
            {
                nowans = nowans * B + (s1[i]-'A'+1);
            }
            if(nowans != lstans)
            {
                printf("NOT UNIQUE\n"); exit(0);
            }
        }
    }
    if(!flag) printf("NOT POSSIBLE\n");
    else cout << ans << endl;

    return 0;
}
View Code

由分类讨论发现得到答案并不需要两个中转string,可以直接拿,并且发现答案的hash已经记录过,然后A个T1居然花了一下午!?

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ll;
const int maxn = 2e6 + 30;

int n, mid, flag;
//ll mod = 1234567891;
ll f[maxn], m[maxn], B = 131, lstans, nowans;
string ans, u;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    n = read(); mid = n/2;
    cin >> u;
    m[0] = 1;
    for(int i=1; i<=n; i++) m[i] = m[i-1] * B;
    n = u.length();
    f[0] = u[0] - 'A' + 1;
    for(int i=1; i<n; i++)
    {
        f[i] = f[i-1] * B + (u[i]-'A'+1);
    }
    for(int i=1; i<=mid; i++)
    {
        ll h1 = f[i-1]*m[mid-i]+f[mid]-f[i]*m[mid-i];
        ll h2 = f[n-1]-f[mid]*m[n-mid-1];
        if(h1 == h2)
        {
            if(!flag)
            {
                string s1 = u.substr(mid+1);
                ans = s1; flag++;
                lstans = h1;
            }
            else 
            {
                nowans = h1;
                if(nowans == lstans) continue;
                else 
                {
                    printf("NOT UNIQUE\n"); exit(0);
                }
            }
        }
    }
    for(int i=mid+1; i<n-1; i++)
    {
        ll h1 = f[mid-1];
        ll h2 = f[n-1]-f[i]*m[n-i-1]+(f[i-1]-f[mid-1]*m[i-mid])*m[n-i-1];
        if(h1 == h2)
        {
            if(!flag)
            {
                string s1 = u.substr(0, mid);
                ans = s1; flag++;
                lstans = h1;
            }
            else 
            {
                nowans = h1;
                if(nowans == lstans) continue;
                else 
                {
                    printf("NOT UNIQUE\n"); exit(0);
                }
            }
        }
    }
    ll h1 = f[mid]-f[0]*m[mid], h2 = f[n-1]-f[mid]*m[mid];
    if(h1 == h2)
    {
        if(!flag) 
        {
            string s1 = u.substr(mid+1);
            ans = s1; flag++;
            lstans = h1;
        }
        else
        {
            nowans = h1;
            if(nowans != lstans)
            {
                printf("NOT UNIQUE\n"); exit(0);
            }
        }
    }
    h1 = f[mid-1]; h2 = f[n-2]-f[mid-1]*m[mid];
    if(h1 == h2)
    {
        if(!flag) 
        {
            string s1 = u.substr(0, mid);
            ans = s1; flag++;
            lstans = h1;
        }
        else 
        {
            nowans = h1;
            if(nowans != lstans)
            {
                printf("NOT UNIQUE\n"); exit(0);
            }
        }
    }
    if(!flag) printf("NOT POSSIBLE\n");
    else cout << ans << endl;

    return 0;
}
View Code

注意事项就是判断重复是作为答案的字符串不能重复,而不是断点必须取同一个,感谢cr的提醒。我本来以为自动溢出会被卡的,毕竟大佬们都在用双模数,然而居然没卡我qwq

 

至于其他3个题去哪了……emmm……我并不会……

不过既然下发标程了,我存个档:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<ctime>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
inline void read(int &x){
        x=0;char ch=getchar();int f=1;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=f;
}
inline void judge(){
        freopen("monkey.in","r",stdin);
        freopen("monkey.out","w",stdout);
}
const int maxn=1000005,mod=1e9+7;
char s[maxn];
int a[maxn],f[maxn],n,trans[maxn][2],sum[maxn],parent[maxn];
int main(){
        //judge();                                                                                  
        scanf("%s",s+1);n=strlen(s+1);
        rep(i,1,n)a[i]=s[i]-'0';
        rep(i,1,n)trans[i][a[i]]=i+1;
        trans[1][a[1]^1]=1;parent[1]=0;trans[0][0]=1;trans[0][1]=1;
        rep(i,2,n){
                parent[i]=trans[parent[i-1]][a[i-1]];
                trans[i][a[i]^1]=trans[parent[i]][a[i]^1];
        }f[1]=sum[1]=1;
//      rep(i,1,n)printf("%d\n",parent[i]);                                                         
        rep(i,2,n){
                sum[i]=sum[i-1];
                int p=trans[i][a[i]^1];
                f[i]=(sum[i]-sum[p-1]+1+(i-p)+mod)%mod;
                sum[i]=(sum[i-1]+f[i])%mod;
        }
//      rep(i,1,n)printf("%d\n",f[i]);                                                              
        int ans=sum[n]+n;
        ans%=mod;
        cout<<ans<<endl;
        return 0;
}
T4
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <set>

#define For(i, j, k) for (int i = j; i <= k; i++)
#define Forr(i, j, k) for (int i = j; i >= k; i--)

using namespace std;

typedef long long LL;

const int N = 1e6 + 10;

LL sumc[N];

struct Segment_Tree {

        const static int NODE = 1 << 21;

        int lc[NODE], rc[NODE], addv[NODE], node;
        LL sum[NODE], sqr[NODE];

        #define M ((L + R) >> 1)

    void modify(int &o, int L, int R, int l, int r) {
                if (!o) o = ++node;
            if (l <= L && R <= r) {
                        addv[o]++;
                } else {
                        if (l <= M) modify(lc[o], L, M, l, r);
                if (r > M) modify(rc[o], M + 1, R, l, r);
                }

                sum[o] = sum[lc[o]] + sum[rc[o]] + (sumc[R] - sumc[L - 1]) * addv[o];
                sqr[o] = sqr[lc[o]] + sqr[rc[o]] + 2ll * addv[o] * sum[o] - (sumc[R] - sumc[L - 1])\
 * addv[o] * addv[o];
    }

        #undef M

}T;

struct Suffix_Automaton {

        int pre[N], ch[N][26], Max[N];
        int node, lst;

    void extend(int c) {
                int p = lst;

                if (ch[p][c]) {
            int q = ch[p][c];
                        if (Max[q] == Max[p] + 1) {
                                lst = q;
                return;
                        }
                int nq = ++node;
                        For(i, 0, 25) ch[nq][i] = ch[q][i];
                pre[nq] = pre[q];
                        pre[q] = nq;
                Max[nq] = Max[p] + 1;
                        while (ch[p][c] == q) ch[p][c] = nq, p = pre[p];
            lst = nq;
                } else {
                    int np = ++node;
            Max[np] = Max[p] + 1;
                    while (!ch[p][c]) ch[p][c] = np, p = pre[p];
                    if (ch[p][c] == np) {
                        pre[np] = p;
                    } else {
                                int q = ch[p][c];
                                if (Max[q] == Max[p] + 1) {
                                pre[np] = q;
                            } else {
                                        int nq = ++node;
                                        For(i, 0, 25) ch[nq][i] = ch[q][i]; pre[nq] = pre[q];
                        pre[q] = nq;
                        Max[nq] = Max[p] + 1;
                    while (ch[p][c] == q) ch[p][c] = nq, p = pre[p];
            lst = nq;
                } else {
                    int np = ++node;
                        Max[np] = Max[p] + 1;
                    while (!ch[p][c]) ch[p][c] = np, p = pre[p];
            if (ch[p][c] == np) {
                                pre[np] = p;
            } else {
                                int q = ch[p][c];
                if (Max[q] == Max[p] + 1) {
                                        pre[np] = q;
                } else {
                                        int nq = ++node;
                                        For(i, 0, 25) ch[nq][i] = ch[q][i];
                    pre[nq] = pre[q];
                                    pre[q] = pre[np] = nq;
                                        Max[nq] = Max[p] + 1;
                    while (ch[p][c] == q) ch[p][c] = nq, p = pre[p];
                                }
            }
                        lst = np;
                }

        }

        void insert(char *S) {
                int l = strlen(S);
                For(i, 0, l - 1) extend(S[i] - 'a');
        lst = 0;
        }

        vector<int> G[N];
        int son[N], sz[N];

    void DFS_init(int o) {
            sz[o] = 1;
        for (int v : G[o]) {
                    DFS_init(v);
                        sz[o] += sz[v];
                if (!son[o] || sz[v] > sz[son[o]]) son[o] = v;
                }
        }

        int top[N];
        int id[N], dfn;
 int top[N];
    int id[N], dfn;

        void DFS_decompose(int o) {
        if (o) {
                        id[o] = ++dfn;
            sumc[dfn] = sumc[dfn - 1] + Max[o] - Max[pre[o]];
                }
                top[o] = pre[o] && son[pre[o]] == o ? top[pre[o]] : o;
        if (son[o]) DFS_decompose(son[o]);
                for (int v : G[o]) {
            if (v == son[o]) continue;
                        DFS_decompose(v);
        }
        }

        void init() {
        For(i, 1, node) G[pre[i]].push_back(i);
                DFS_init(0);
                DFS_decompose(0);
    }

    int root;
void modify(char *S) {
                int l = strlen(S), o = 0;
        For(i, 0, l - 1) {
                        o = ch[o][S[i] - 'a'];
                    int p = o;
            while (p) {
                                T.modify(root, 1, dfn, id[top[p]], id[p]);
                            p = pre[top[p]];
            }
                }
        printf("%lld\n", T.sqr[root]);
        }

}M;

int n;
char *S[N], buffer[N];

int main() {

        scanf("%d", &n);
    char *p = buffer;
        For(i, 1, n) {
        S[i] = p;
                scanf("%s", p);
                p += strlen(S[i]) + 1;
            M.insert(S[i]);
    }
    M.init();
    For(i, 1, n) M.modify(S[i]);

        return 0;
}
T3
e <cstdio>
#include <cstdlib>
#include <assert.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

// head                                                                                                                                                                                       

const int N=101000;
int w[N],c[N],n;
ll s[N],c0[N],c1[N];
void solve() {
        rep(i,0,n) scanf("%d",w+i);
        if (*min_element(w,w+n)>=0) {
                puts("0");
                return;
        }
        rep(i,1,n+1) s[i]=s[i-1]+w[i-1];
        int k=max_element(s+1,s+n+1)-s;
        rotate(w,w+k,w+n);
        rep(i,1,n+1) s[i]=s[i-1]+w[i-1];
        ll cnt=0;
        rep(i,1,n+1) c[i]=0;
        vector<ll> v;
        rep(i,1,n) v.pb(s[i]);
        sort(all(v));
        per(i,1,n) {
                int x=lower_bound(all(v),s[i])-v.begin()+1;
                for (int y=x-1;y;y-=y&-y) cnt+=c[y];
                for (int y=x;y<=n;y+=y&-y) c[y]++;
        }
        sort(s+1,s+n);
        int m=s[n];
        if (m<=0) {
                puts("-1");
                return;
rep(i,0,m) c0[i]=c1[i]=0;
        rep(i,1,n) s[i]=-s[i]+m;
        reverse(s+1,s+n);
        for (int i=1;i<n;i++) {
                int j=i;
                while (j+1<n&&s[j+1]==s[i]) j++;
                int c=j-i+1; ll v=s[i];
                cnt+=(v-1)/m*c;
                rep(j,0,m) cnt+=c*((v/m-(v%m<j))*c0[j]-c1[j]);
                v++;
                c0[v%m]+=c; c1[v%m]+=c*(v/m);
                i=i+c-1;
        }
        printf("%lld\n",cnt);
}
int main() {
        // freopen("elasticity.in","r",stdin);freopen("elasticity.out","w",stdout);                                                                                                           
        while (scanf("%d",&n),n!=0) solve();
}
T2

 

posted @ 2022-10-06 17:45  Catherine_leah  阅读(25)  评论(2编辑  收藏  举报
/* */