ACM校赛网络赛部分题解

这次网络赛我共出了三题,现给出题解

自动售货机

由于测试样例很多,每次都计算会超时,所以要打表,递推方程为dp[i][j]=dp[i-1][j]+dp[i-1][j-1];注意优化剪枝,在dp循环过程中如果不剪枝,实打实的2000*1000也是会超时的。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;
int dp[2005][1005];
const int mod=(1e9+7);
int main()
{
    //freopen("in3.txt","r",stdin);
    //freopen("out3.txt","w",stdout);
    dp[1][0]=1;
    for(int i=2;i<=2000;i++)
    {
        dp[i][0]=1;
        int len=i/2;
        for(int j=1;j<=len;j++)
        {
            dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]);
            if(dp[i][j]>=mod)
            dp[i][j]%=mod;
        }
    }
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        printf("%d\n",dp[n+m][m]);
    }
    return 0;
}
 

KSS金牌梦1

map离散化+变化的拓扑排序,时限比较紧,实在没想到OJ运行速度如此慢,本机上1s不到,我的锅。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int MAXN=505;
int g[MAXN][MAXN],in[MAXN];
bool vis[MAXN];
int main()
{
    //freopen("in1.txt","r",stdin);
    int n,m,cnt;
    while(~scanf("%d",&n))
    {
        map<string,int> mp;
        cnt=1;
        memset(g,0,sizeof(g));
        memset(in,0,sizeof(in));
        memset(vis,false,sizeof(vis));
        while(n--)
        {
            char a[50],b[50];
            //string a,b;
            scanf("%s%s",a,b);
            if(mp[a]==0)mp[a]=cnt++;
            if(mp[b]==0)mp[b]=cnt++;
            g[mp[b]][mp[a]]=1;
            in[mp[a]]++;//cout<<n<<endl;
        }
        bool flag=false;
        for(int i=1;i<cnt;i++)
        {
            for(int j=1;j<cnt;j++)
            {
                if(in[j]==0 && !vis[j])
                {
                    vis[j]=1;
                    flag=true;
                    for(int k=1;k<cnt;k++)
                        if(g[j][k])
                            in[k]--;
                    break;
                }
            }
            if(flag==false)
                break;
            flag=false;
        }
        scanf("%d",&m);
        int num=0;
        for(int i=0;i<m;i++)
        {
            string a;
            cin>>a;
            if(mp[a]>0 && vis[mp[a]]) num++;
        }
        if(1.0*num/m>0.7)
        cout<<"Excelsior!"<<endl;
        else
        cout<<"KSS have a dream!"<<endl;
    }
    return 0;
}


KSS金牌梦2 

离线存储,按距离排序,加入主席树,维护区间和与覆盖次数两个属性,二分位置查询得出结果,WA点很多很多很多很多,又是我的锅。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<time.h>
using namespace std;
const int MAXN=100005;
struct node
{
    int l,d,val,flag;
}in[MAXN<<1];
struct node1
{
    int x,a,b,c;
}in2[MAXN];
struct tree
{
    int l,r,cnt,flag[2];
    long long val;
}tree[MAXN*35];
int root[MAXN<<1],pos;
bool cmp1(node a,node b)
{
    return a.d<b.d;
}
bool cmp2(node a,node b)
{
    return a.l<b.l;
}
void pushup(int now)
{
    tree[now].cnt=0;
    tree[now].val=0;
    if(tree[now].flag[0]!=-1)
    {
        tree[now].cnt+=tree[tree[now].flag[0]].cnt;
        tree[now].val+=tree[tree[now].flag[0]].val;
    }
    if(tree[now].flag[1]!=-1)
    {
        tree[now].cnt+=tree[tree[now].flag[1]].cnt;
        tree[now].val+=tree[tree[now].flag[1]].val;
    }
}
int build(int l,int r)
{
    int now=pos++;
    tree[now].l=l;
    tree[now].r=r;
    tree[now].cnt=tree[now].val=0;
    tree[now].flag[0]=tree[now].flag[1]=-1;
    if(l==r)
        return now;
    int mid=(l+r)>>1;
    tree[now].flag[0]=build(l,mid);
    tree[now].flag[1]=build(mid+1,r);
    return now;
}
int update(int l,int r,int v,int v1,int pre,int flag)
{
    int now=pos++;
    tree[now].l=l;
    tree[now].r=r;
    tree[now].flag[0]=tree[pre].flag[0];
    tree[now].flag[1]=tree[pre].flag[1];
    tree[now].cnt=tree[pre].cnt;
    tree[now].val=tree[pre].val;
    if(l==r)
    {
        if(flag)
        {
            tree[now].cnt--;
            tree[now].val-=v1;
        }
        else
        {
            tree[now].cnt++;
            tree[now].val+=v1;
        }
        return now;
    }
    int mid=(l+r)>>1;
    if(v<=mid)
        tree[now].flag[0]=update(l,mid,v,v1,tree[pre].flag[0],flag);
    else
        tree[now].flag[1]=update(mid+1,r,v,v1,tree[pre].flag[1],flag);
    pushup(now);
    return now;
}
long long query(int l,int r,int now,long long k)
{
    if(l==r)
    {
            if(tree[now].cnt==0)
                return 0;
            return tree[now].val/tree[now].cnt*k;
    }
    int mid=(l+r)>>1;
    long long ans=0;
    if(k<=tree[tree[now].flag[0]].cnt)
        ans+=query(l,mid,tree[now].flag[0],k);
    else
        ans+=tree[tree[now].flag[0]].val+query(mid+1,r,tree[now].flag[1],k-=tree[tree[now].flag[0]].cnt);
    return ans;
}
int main()
{
    //freopen("in2.txt","r",stdin);
    //freopen("out2.txt","w",stdout);
    int n,m,x,p;
    while(~scanf("%d%d%d%d",&n,&m,&x,&p))
    {
        long long prescore=1;
        pos=0;
        int l,r,d,num=1;
        for(int i=1;i<=n;i++)
        {
                scanf("%d%d%d",&l,&r,&d);
                in[num].l=l;
                in[num].d=d;
                in[num++].flag=0;
                in[num].l=r+1;
                in[num].d=d;
                in[num++].flag=1;
        }
        for(int i=0;i<m;i++)
            scanf("%d%d%d%d",&in2[i].x,&in2[i].a,&in2[i].b,&in2[i].c);
        sort(in+1,in+num,cmp1);
        int cnt=0;
        in[num].d=-1;
        for(int i=1;i<num;i++)
            if(in[i].d!=in[i+1].d)
                in[i].val=cnt++;
            else
                in[i].val=cnt;
        sort(in+1,in+num,cmp2);
        root[0]=build(0,cnt-1);
        for(int i=1;i<num;i++)
            root[i]=update(0,cnt-1,in[i].val,in[i].d,root[i-1],in[i].flag);
        for(int i=0;i<m;i++)
        {
                int low=1,high=n*2;
                int ans1=0;
                while(low<=high)
                {
                    int mid=(low+high)>>1;
                    if(in[mid].l<=in2[i].x)
                    {
                        ans1=mid;
                        low=mid+1;
                    }
                    else
                        high=mid-1;
                }
                long long nowk=((long long)in2[i].a*prescore+(long long)in2[i].b)%(long long)in2[i].c;
                int flag=0;
                if(prescore>p)
                    flag=1;
                if(ans1)
                {
                    if(nowk>=tree[root[ans1]].cnt)
                    {
                        prescore=(tree[root[ans1]].val);
                        if(flag)
                        prescore*=2;
                    }
                    else
                    {
                        prescore=query(0,cnt-1,root[ans1],nowk);
                        if(flag)
                        prescore*=2;
                    }
                }
                else
                    prescore=0;
                printf("%I64d\n",prescore);
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值