2014 西安网络赛部分题解

提交地址


1002 Boring String Problem

后缀数组+RMQ+二分

后缀数组二分确定第K不同子串的位置 , 二分LCP确定可选的区间范围 , RMQ求范围内最小的sa

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define prt(k) cout<<#k" = "<<k<<endl;
const int N = 100010;
int sa[N], rank[N], rank2[N], h[N],c[N], *x, *y, ans[N];
typedef long long ll;
char str[N];

bool cmp(int* r, int a, int b, int l, int n)
{
    return r[a]==r[b] && a+l<n && b+l<n && r[a+l]==r[b+l];
}
void radix_sort(int n,int sz)
{
    for(int i=0; i<sz; i++) c[i]=0;
    for(int i=0; i<n; i++) c[x[y[i]]]++;
    for(int i=1; i<sz; i++) c[i]+=c[i-1];
    for(int i=n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i];
}
void get_sa(char c[],int n,int sz=128)
{
    x=rank,y=rank2;
    for(int i=0;i<n;i++) x[i]=c[i],y[i]=i;
    radix_sort(n,sz);
    for(int len=1;len<n;len<<=1)
    {
        int yid=0;
        for(int i=n-len;i<n;i++) y[yid++]=i;
        for(int i=0;i<n;i++) if(sa[i]>=len) y[yid++]=sa[i]-len;
        radix_sort(n,sz);
        swap(x,y);
        x[sa[0]]=yid=0;
        for(int i=1;i<n;i++)
        {
            x[sa[i]]=cmp(y,sa[i],sa[i-1],len,n) ? yid : ++yid;
        }
        sz=yid+1;
        if(sz>=n) break;
    }
    for(int i=0;i<n;i++) rank[i]=x[i];
}
void get_h(char str[],int n)
{
    int k=0; h[0]=0x3f3f3f3f;
    for(int i=0;i<n;i++)
    {
        if(rank[i]==0) continue;
        k=max(k-1,0);
        int j=sa[rank[i]-1];
        while(i+k<n && j+k<n && str[i+k]==str[j+k]) k++;
        h[rank[i]]=k;
    }
}
int dp[N][20];
int mmm[N][22];
void RMQ_init(int n)
{
    for(int i=0;i<n;i++) dp[i][0]=h[i], mmm[i][0]=sa[i];
    dp[0][0]=0x3f3f3f3f;
    for(int i=1;(1<<i)<=n;i++)
    {
        for(int j=0;j+(1<<i)-1<n; j++)
            dp[j][i]=min(dp[j][i-1], dp[j+(1<<(i-1))][i-1]),
            mmm[j][i]=min(mmm[j][i-1], mmm[j+(1<<(i-1))][i-1]);
    }
}
int LCP(int l,int r,int n)
{
    if(l==r) return n-sa[l];
    l++;
    if(l>r) swap(l,r);
    int k = 0;
    while(1<<(k+1) <= r-l+1) k++;
    return min(dp[l][k],dp[r-(1<<k)+1][k]);
}
ll Range[N];
int bin(ll x, int n)
{
    int ans = -1;
    int l=0, r=n-1, mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(Range[mid]<x) ans=mid,l=mid+1;
        else r=mid-1;
    }
    return ans;
}
int MMM(int l, int r)
{
    if(l>r) swap(l,r);
    int k = 0;
    while(1<<(k+1) <= r-l+1) k++;
    return min(mmm[l][k], mmm[r-(1<<k)+1][k]);
}
int binID(int x,int n,int len)
{
    int ans=x;
    int l=x,r=n-1,mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(LCP(x,mid,n)>=len)
        {
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    return ans;
}
int main()
{
while(scanf("%s",str)==1)
{
    int n=strlen(str);
    get_sa(str,n);
    get_h(str,n);
    RMQ_init(n);
    h[0]=0;
    for(int i=0;i<n;i++)
    {
        Range[i] = (n-sa[i])-h[i];
        if(i-1>=0) Range[i]+=Range[i-1];
    }
    int q; cin>>q;
    int L=0,R=0;
    while(q--)
    {
        ll V; scanf("%I64d",&V);
        ll K = (L^R^V) + 1;
        if(K>Range[n-1])
        {
            L=0, R=0;
            printf("0 0\n");
            continue;
        }
        int id = bin(K,n);
        ll jian=0;
        if(id>=0) jian=Range[id];
        ll res=K-jian;
        id++;
        int len=h[id]+res;
        int hid=binID(id,n,len);
        int Left=MMM(id,hid);
        L=Left+1, R=Left+len;
        printf("%d %d\n",L,R);
    }
}
}

1003 Paint Pearls

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define prt(k) cout<<#k" = "<<k<<endl;
const int N = 50010;
#include<map>
#include<algorithm>
int a[N];
int n;
int dp[N];
int b[N];
int fa[N];
int f(int x) { return x==fa[x]?x:fa[x]=f(fa[x]); }
void U(int x, int y) { x=f(x),y=f(y); if(x-y) fa[y]=x; }
int sqr(int x) { return x * x; }
int last[N];
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        
        for(int i = 1; i <= n; i++) b[i] = a[i];
        map<int,int> mp;
        sort(b+1, b+n+1);
        int m = unique(b+1, b+n+1) - (b+1);
        for(int i=1;i<=m;i++) mp[b[i]] = i ;
        for(int i = 1; i<=n; i++) a[i] = mp[a[i]] ,fa[i]=i, last[i]=-1;

        dp[0] = 0;
        map<int,int> tmp;
        for(int i = 1; i <= n; i++)
        {
            if(~last[a[i]]) U(last[a[i]]-1, last[a[i]]);
            last[a[i]] = i;
            dp[i] = i;
            int c = 0;
            for(int j = i; j>0 ; j=f(j-1))
            {
                c++;
                if( c*c > dp[i]) break;
                dp[i] = min(dp[i], dp[f(j-1)] + c*c );
            }
        }
        cout<<dp[n]<<endl;
    }
}


1009  233 Matrix

首先A[0][n]  = A[0][n - 1] * 10 + 3

然后A[m] [n]  = A[m] [n - 1] + A[m - 1][n - 1] + ... + A[1][n - 1] + A[0][n]

然后A[m] [n]  = A[m] [n - 1] + A[m - 1][n - 1] + ... + A[1][n - 1] + (A[0][n - 1] * 10 + 3)

然后A[m] [n]  = 3 + 10 * A[0][n - 1]  +A[1] [n - 1] + A[2][n - 1] + ...  + A[m - 1][n - 1] + A[m][n - 1]

就能看出,A[*][n] 是A[*][n - 1]的线性表示了。

233 Matrix
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#include<vector>
typedef long long ll;
#define prt(k) cout<< #k" = " << k<< "   \n";   ///

const ll mod = 10000007;
int n,m;
void add(ll &a, ll b)
{
    a=(a+b)%mod;
}
struct Matrix
{
    ll a[22][22];
    Matrix()
    {
        memset(a,0,sizeof a);
    }
    Matrix operator*(Matrix b)
    {
        Matrix c;
        for(int i = 0; i < n; i++) for(int j =0; j<n; j++)
        {
            c.a[i][j]= 0;
            for(int k = 0; k < n; k ++)
                add(c.a[i][j], a[i][k] * b.a[k][j] % mod);
        }
        return c;
    }
    void out()
    {
        for(int i =0; i<n; i++)
        {
            for(int j = 0 ; j < n; j++) cout<<a[i][j]<<' ';
            cout << endl;
        }
    }
};
Matrix pow(Matrix a, int m)
{
    Matrix res;  int i,j;
    for(i = 0; i < ::n; i++) for(j = 0; j < ::n; j++) res.a[i][j] = (i == j);
    for(; m>0; m>>=1, a=a*a) if(m&1) res = res * a;
    return res;
}
int main()
{
    while(cin >> n >> m)
    {
        n += 2;
        int a[22];
        a[0] = 3;
        a[1] = 23;
        for(int i = 2; i < n; i ++) cin>>a[i];
        Matrix ma;
        for(int i = 0 ; i < n; i++)
        {
            int j;
            for( j = 0 ; j<=i; j++)
                if(j == 1) ma.a[i][j] = 10;
                else  ma.a[i][j] = 1;
            for(; j<n; j++) ma.a[i][j] = 0;
        }
        ;
        ma = pow(ma, m);

        ll ans= 0; // cout<<ma.a[0][0];
        for(int i = 0; i<n; i++) add(ans, ma.a[n-1][i] * a[i] % mod);
        cout << ans << endl;
    }
}

1011 Ellipsoid
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define prt(k) cout<<#k" = "<<k<<endl;
const double eps = 1e-8;
int dx[]={0,0,1,1,1,-1,-1,-1};
int dy[]={1,-1,0,1,-1,0,1,-1};
const double inf = 1e30;
double dist(double x,double y,double z)
{
    return sqrt(x*x+y*y+z*z);
}
double a,b,c,d,e,f;
double getz(double x,double y)
{
    double A=c,B=d*y+e*x,C=a*x*x+b*y*y+f*x*y-1;
    double delta=B*B - 4*A*C;
    if(delta<0) return inf;
    double z1=(-B+sqrt(delta))/2/A;
    double z2=(-B-sqrt(delta))/2/A;
    if(z1*z1<z2*z2) return z1;
    else return z2;
}
double solve()
{
    double step=1;
    double x=0,y=0,z;
    while(step>eps)
    {
        z=getz(x,y);
        for(int i=0;i<8;i++)
        {
            double nx=x+dx[i]*step;
            double ny=y+dy[i]*step;
            double nz=getz(nx,ny);
            if(nz>=inf) continue;
            if(dist(nx,ny,nz)<dist(x,y,z))
            {
                x=nx,y=ny,z=nz;
            }
        }
        step*=0.99;
    }
    return dist(x,y,z);
}
int main()
{
    while(cin>>a>>b>>c>>d>>e>>f)
    {
        printf("%.9f\n", solve());
    }
    return 0;
}



你可能感兴趣的:(2014 西安网络赛部分题解)