BestCoder Round #58

来源:互联网 发布:淘宝玻璃茶具套装 编辑:程序博客网 时间:2024/05/16 05:02

hdu5494 Problem 0. Card Game

怎么选择m个数都能赢,最小的m个数之和大于对方的最大的m个数之和就好了。

#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <algorithm>#include <stdlib.h>#include <map>#include <vector>#define rep(i,n) for(i=0;i<n;i++)#define cle(x) memset(x,0,sizeof(x))#define ll long longconst int maxn=1000+5;using namespace std;int main(){#ifndef ONLINE_JUDGE     freopen("in.txt","r",stdin);     //freopen("out.txt","w",stdout);#endif    int T;    cin>>T;    int a[maxn],b[maxn],n,m;    while(T--){        cin>>n>>m;        int i;rep(i,n)cin>>a[i];        rep(i,n)cin>>b[i];        int sum[maxn];        sort(a,a+n);sort(b,b+n);        int ip=0;rep(i,n){            if(i==0)sum[i]=a[i];            else sum[i]=sum[i-1]+a[i];        }        int sumb[maxn];        for(i=n-1;i>=0;i--){            if(i==n-1)sumb[ip++]=b[i];            else sumb[ip++]=sumb[ip-1]+b[i];        }        if(sum[m-1]>sumb[m-1])cout<<"YES"<<endl;        else cout<<"NO"<<endl;    }    return 0;}

hdu 5495 Problem 1. LCS

题意

子序列,按照相同的排列顺序,重新排列,是相同子序列最长。

解法

每个环之间是独立的,在独立的一个环上的选择,最优情况要舍掉一个数字,比如1->2 2->3 3->4 4->1 序列(1,2,3,4)和序列(2,3,4,1)就要舍掉1

#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <algorithm>#include <stdlib.h>#include <map>#include <vector>#define rep(i,n) for(i=0;i<n;i++)#define cle(x) memset(x,0,sizeof(x))#define ll long longconst int maxn=100000+5;using namespace std;int a[maxn],b[maxn],u[maxn];int v[maxn];int main(){#ifndef ONLINE_JUDGE     freopen("in.txt","r",stdin);     //freopen("out.txt","w",stdout);#endif    int T;    cin>>T;    int n;    while(T--)    {        cle(v);        cin>>n;        int i;        rep(i,n)        {            scanf("%d",&a[i]);        }        rep(i,n)        {            scanf("%d",&b[i]);        }        rep(i,n)        {            u[a[i]]=b[i];        }        int ans=0;        rep(i,n)        {            if(a[i]==b[i])            {                ans++;                v[a[i]]=1;                continue;            }            if(v[a[i]]==0)            {                v[a[i]]=1;                int temp=1;                int now=u[a[i]];                while(true)                {                    if(v[now])                    {                        break;                    }                    else                    {                        v[now]=1;                        temp++;                        now=u[now];                    }                }                ans+=temp;                ans--;            }        }        cout<<ans<<endl;    }    return 0;}

hdu 5496 Problem 2. Beauty of Sequence

题意:

所有子序列和之和,子序列中连续相邻相同元素只算一次。

解法:

官方解法:一个数的如果是几个连续相同数的第一个,他的贡献计算。
总的方案数=之前的方案数*之后的方案数
之前的方案数=所有方案数-以和他相同数作为倒数第二个的方案数 用map统计就好了

#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <algorithm>#include <stdlib.h>#include <map>#include <vector>#define rep(i,n) for(i=0;i<n;i++)#define cle(x) memset(x,0,sizeof(x))#define ll long longconst int maxn=100000+5;const int mod=1e9+7;using namespace std;ll a[maxn];ll b[maxn];int n;void init(){    b[0]=0;    for(int i=1;i<maxn;i++){        b[i]=(b[i-1]*2+1)%mod;    }      }map<ll,ll>mp;void doit(){    mp.clear();ll sum=0;    for(int i=1;i<=n;i++)    {        ll be=(b[i-1]+1-mp[a[i]]+mod)%mod;//之前的        ll en=b[n-i]+1;//之后的        sum=((sum+((a[i]*((be*en)%mod))%mod))%mod);        mp[a[i]]=(mp[a[i]]+b[i-1]+1)%mod;    }    cout<<sum<<endl;}int main(){#ifndef ONLINE_JUDGE     freopen("in.txt","r",stdin);     //freopen("out.txt","w",stdout);#endif    int T;cin>>T;init();    while(T--)    {        cin>>n;        for(int i=1;i<=n;i++){            scanf("%I64d",&a[i]);        }        doit();    }    return 0;}

hdu 5497 Problem 3. Inversion

题意:

一个序列 ,可以删除一个长度为m的连续子序列. 问如何删除才能使逆序对最少。

解法:

删掉的应该是构成逆序对最多那些
向前连线(比他大的)
向后两线(比他小的)
选择的区间可能重复计算了。连接的两端都在区间内。
删掉的数目=所有的连线(每个数向前连线+向后连线)-区间内构成的逆序对个数(一个树状数组可维护,能想到怎么维护就可以解决了)

备注:

由于我自己写的思路比较露骨,所以有时提交超时有时候AC,可以加一些输入输出挂之类的~

#include <cstdio>#include <iostream>#include <cmath>#include <cstring>#include <algorithm>#include <stdlib.h>#include <map>#include <vector>#define rep(i,n) for(i=0;i<n;i++)#define cle(x) memset(x,0,sizeof(x))#define ll long longconst int maxn=100000+5;using namespace std;ll a[maxn],rea[maxn];ll b[maxn],qu[maxn];ll sum[maxn];int lowbit(int x){    return x&(-x);}ll getsum(int x){    ll re=0;    for(int i=x-1;i>0;i-=lowbit(i))re+=sum[i];    return re;}void update(int x,ll y){    for(int i=x;i<maxn;i+=lowbit(i))sum[i]+=y;}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);     //freopen("out.txt","w",stdout);#endif    int T;    cin>>T;    while(T--)    {        int n,m;        scanf("%d%d",&n,&m);        int i;        rep(i,n){            scanf("%I64d",&a[i]);rea[i]=n-a[i]+1;}        cle(sum);ll cot=0;        for(i=n-1;i>=0;i--){            b[i]=getsum(a[i]);cot+=b[i];            update(a[i],1);        }        if(m==0||cot==0){            printf("%I64d\n",cot);            continue;        }        cle(sum);        rep(i,n){            b[i]+=getsum(rea[i]);//每个位置构成逆序对,向前向后之和            update(rea[i],1);        }        cle(sum);qu[0]=0;        for(i=0;i<m;i++){            qu[0]+=getsum(rea[i]);//维护第一个m个连续的数的逆序对个数            update(rea[i],1);        }int ip=1;        for(i=1;i<=n-m;i++){            qu[ip]=qu[ip-1]-(getsum(n+1)-getsum(rea[i-1]+1));//去掉第一个数的构成个数            update(rea[i-1],-1);            qu[ip]+=getsum(rea[i+m-1]);//加上最新数构成个数            update(rea[i+m-1],1);            ip++;        }        ll maxans=0;ll now=0;        for(i=0;i<m;i++)now+=b[i];        for(i=0;i<=n-m;i++){            maxans=max(maxans,now-qu[i]);            now-=b[i];now+=b[i+m];        }        printf("%I64d\n",cot-maxans);    }    return 0;}

hdu 5498 Problem 4. Tree

现如今能力不足~

0 0
原创粉丝点击