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

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;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
extra qualification timerevent是指额外的资格和时间活动。这是一个广泛的概念,可以指任何一种能够增加个人技能和知识的额外资格或时间活动。 在职场中,个人可以通过参加专业培训课程、研讨会和工作坊来获取额外的资格和时间活动。这些活动可以为他们提供新的技能和知识,使他们在职场中更加具有竞争力。此外,个人还可以通过参加行业认证考试来获得额外的资格,这些认证可以证明他们具备特定领域的专业知识和技能。通过参与这些额外的资格和时间活动,个人可以增加自己在职场中的价值和机会。 在教育领域,学生可以通过参加额外的课外培训活动来提高自己的学术水平和技能。这些活动可以包括参加学术竞赛、科研项目、社会实践等,这些活动可以拓宽学生的眼界,培养他们的创造力和领导能力。此外,学生还可以通过参加语言培训班、艺术培训班等增加自己的技能和知识。这些额外的资格和时间活动可以为学生提供更多的机会,帮助他们在学术和职业领域取得成功。 总的来说,额外的资格和时间活动对个人和学生来说都是非常有益的。这些活动可以帮助他们提高自己的技能和知识,增加他们在职场和学术领域的竞争力。而且,额外的资格和时间活动也能为个人提供更多的机会和发展空间。因此,我们鼓励每个人都参与额外的资格和时间活动,不断提升自己。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值