VK Cup 2012 Qualification Round 2部分题解(C,D,E)

来源:互联网 发布:数据库物理模型主键 编辑:程序博客网 时间:2024/04/30 00:03

CF上的一场资格赛,有二十四小时的时间给我们做,所以为了晋级,我和队友合力弄掉了四题,而最后的E题其实也不难,后来也过了……因为A,B相对较水,所以以下只讲后三题……

contest

C题:

比赛时一致认为暴力不行,比赛后发现很多都是暴力过的……因此,比赛时用到了树状数组……其实是队友做出的,无限YM……不过树状数组真是个好东西啊……

#include<iostream>#include<cstring>#include<string>using namespace std;#define M (1<<18)int cl[26][M];             //cl[i][j]表示的是第i种字母在数高为j里的数目int lowbit(int x){return x&(-x);}void add(int id,int pos,int v){while(pos<M){cl[id][pos]+=v;pos+=lowbit(pos);}}int find(int id,int x){int i,ans,cnt;ans=cnt=0;for(i=18;i>=0;i--){ans+=(1<<i);if(ans>=M||cnt+cl[id][ans]>=x)ans-=(1<<i);else cnt+=cl[id][ans];}return ans+1;}int main(){//freopen("a.txt","r",stdin);int i,k,n,x,id,pos,len;char c;string s,str;cin>>n>>s;str="#";for(i=0;i<n;i++)str+=s;len=str.size();for(i=1;i<len;i++){id=str[i]-'a';add(id,i,1);             //建树}cin>>k;while(k--){cin>>x>>c;id=c-'a';pos=find(id,x);             //找此点目前的位置str[pos]='#';add(id,pos,-1);             //删点}for(i=0;i<len;i++){if(str[i]=='#')continue;cout<<str[i];}cout<<endl;return 0;}

D题:

这题是一道挺好的dp,里面的数组f[i][j]表示的是字符串i到j的回文的数目,sum[i]表示的是i后面(包括i)的回文的数目……

#include<iostream>using namespace std;__int64 f[2005][2005];int main(){    //freopen("a.txt","r",stdin);    __int64 i,j,k,l,len,sum[2005];    char s[2005];    scanf("%s",s);    len=strlen(s);    memset(f,0,sizeof(f));    for(i=0;i<len;i++)f[i][i]=1;             //只有一个字符时,回文数为1    for(i=1;i<len;i++)             //i表示间距        for(j=0;i+j<len;j++)        {            k=i+j;            if(s[j]==s[k])            {                if(i==1)f[j][k]=1;                else f[j][k]=f[j+1][k-1];             //只有j和k中间的那一段是回文,j到k才是回文            }        }    memset(sum,0,sizeof(sum));    for(i=0;i<len;i++)        for(j=i;j<len;j++)            sum[i]+=f[i][j];             //这时sum[i]以i为起点的后面的回文数    for(i=0;i<len;i++)        for(j=i+1;j<len;j++)            sum[i]+=sum[j];             //这里sum[i]加上i后面不同起点的回文数    l=0;    for(i=0;i<len;i++)        for(j=i;j<len;j++)            if(f[i][j])l+=sum[j+1];    printf("%I64d\n",l);    return 0;}


E题:

超级模拟题,不多说,直接看代码……

#pragma warning(disable:4786)#include<iostream>#include<algorithm>#include<cstdio>#include<vector>#include<map>using namespace std;struct T{    int c,d;    __int64 h;}p[100005];bool cmp(T x,T y){    return x.c!=y.c?x.c<y.c:x.h>y.h;}__int64 h1[100005],h2[100005],a2[100005];vector<int> g,a1[100005];vector<T> v[100005];map<int,int> m;int main(){    //freopen("a.txt","r",stdin);    int d,i,j,k,l,s,n,y1,y2,len,i1,j1,y3,y4;    __int64 w,x1,x2,Max;    T t;    m.clear();    scanf("%d",&n);    for(i=0;i<n;i++)v[i].clear();    for(i=0;i<n;i++)    {        scanf("%d%I64d",&p[i].c,&p[i].h);        p[i].d=i+1;    }    sort(p,p+n,cmp);    d=p[0].c;    l=1;    m[d]=l++;    for(i=1;i<n;i++)        if(p[i].c!=d)        {            d=p[i].c;            if(!m[d])m[d]=l++;        }    for(i=0;i<n;i++)    {        d=m[p[i].c];        w=p[i].h;        if(v[d].size())w+=v[d][v[d].size()-1].h;        t.h=w,t.d=p[i].d;        v[d].push_back(t);    }    len=0;    memset(h1,0,sizeof(h1));    memset(h2,0,sizeof(h2));    for(i=1;i<l;i++)    {        for(j=0;j<v[i].size();j++)        {            if(h1[j+1]<=v[i][j].h)            {                if(h1[j+1]==v[i][j].h)                {                    a1[j+1].push_back(i);                    continue;                }                if(a1[j+1].size())                {                    h2[j+1]=h1[j+1];                    a2[j+1]=a1[j+1][0];                }                h1[j+1]=v[i][j].h;                a1[j+1].clear();                a1[j+1].push_back(i);            }            else            {                if(h2[j+1]<v[i][j].h)                {                    h2[j+1]=v[i][j].h;                    a2[j+1]=i;                }            }        }        if(len<v[i].size())len=v[i].size();    }    Max=0;    for(i=1;i<=len;i++)    {        x1=h1[i];        for(j=i-1;j<i+2;j++)        {            if(j==0||j==len+1)continue;            x2=h1[j];            for(k=0;k<a1[i].size();k++)            {                y1=a1[i][k];                for(l=0;l<a1[j].size();l++)                {                    y2=a1[j][l];                    if(y1!=y2)break;                }                if(l!=a1[j].size())break;            }            if(k==a1[i].size())            {                x2=h2[j];                y2=a2[j];            }            if(x2==0)continue;            if(Max<x1+x2)            {                Max=x1+x2;                s=i+j;                i1=i,j1=j,y3=y1,y4=y2;            }        }    }    g.clear();    d=i1<j1?i1:j1;    if(i1<j1)swap(y3,y4);    for(i=0;i<d;i++)    {        g.push_back(v[y3][i].d);        g.push_back(v[y4][i].d);    }    if(i1!=j1)g.push_back(v[y3][i].d);     printf("%I64d\n%d\n",Max,s);    for(i=0;i<g.size();i++)    {        if(i)printf(" ");        printf("%d",g[i]);    }    printf("\n");    return 0;}





原创粉丝点击