2017.10.28 QB模拟赛 —— 下午

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017.10.28 QB模拟赛 —— 下午相关的知识,希望对你有一定的参考价值。

题目链接

 

T1

按x值排序 

遇到第二种牌插入 遇到第一种牌 查询<=y 的最小值 删除他 

splay multiset

cys大佬说 multiset就是不去重的set,

技术分享
#include <algorithm>
#include <cstdio>
#define N 100005
using namespace std;

struct node
{
    int x,y,opt;
    bool operator<(node a)const
    {
        if(opt!=a.opt&&x==a.x) return opt>a.opt;
        else return x<a.x;
    }
}card[N<<1];
int n,ans,root,cn,siz[N],cnt[N],data[N],fa[N],ch[N][2];
inline void pushup(int rt)
{
    int l=ch[rt][0],r=ch[rt][1];
    siz[rt]=siz[l]+siz[r]+cnt[rt];
}
inline void ins(int &rt,int x)
{
    if(!rt)
    {
        rt=++cn;
        data[cn]=x;
        siz[cn]=cnt[cn]=1;
        return;
    }
    if(data[rt]==x)
    {
        cnt[rt]++;
        siz[rt]++;
        return;
    }
    if(x<data[rt])
    {
        ins(ch[rt][0],x);
        fa[ch[rt][0]]=rt;
        pushup(rt);
    }
    else 
    {
        ins(ch[rt][1],x);
        fa[ch[rt][1]]=rt;
        pushup(rt);
    }
}
int ask_pre(int rt,int x)
{
    int p=rt,ret=0x7fffffff;
    while(p)
    {
        if(x<data[p]) p=ch[p][0];
        else 
        {
            ret=data[p];
            p=ch[p][1];
        }
    }
    return ret;
}
inline int son(int x) {return ch[fa[x]][1]==x;}
void rotate(int x)
{
    int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
    if(z) ch[z][c]=x;
    else root=x;
    fa[x]=z;
    if(a) fa[a]=y;
    ch[x][!b]=y;ch[y][b]=a;
    fa[y]=x;
    pushup(y);pushup(x);
}
void splay(int x,int i)
{
    while(fa[x]!=i)
    {
        int y=fa[x],z=fa[y];
        if(z==i) rotate(x);
        else 
        {
            if(son(y)==son(x)) rotate(y),rotate(x);
            else rotate(x),rotate(x);
        }
    }
}
int getmn(int rt)
{
    int ret=-1,p=rt;
    while(p)
    {
        ret=p;
        p=ch[p][0];
    }
    return ret;
}
void del(int rt,int x)
{
    if(data[rt]==x)
    {
        if(cnt[rt]>1)
        {
            cnt[rt]--;
            siz[rt]--;
        }
        else
        {
            splay(rt,0);
            int p=getmn(ch[rt][1]);
            if(p!=-1)
            {
                splay(p,rt);
                root=p;fa[p]=0;
                ch[p][0]=ch[rt][0];
                fa[ch[rt][0]]=p;
            }
            else 
            {
                root=ch[rt][0];
                fa[ch[rt][0]]=0;
            }
        }
        return;
    }
    if(x<data[rt])
    {
        del(ch[rt][0],x);
        pushup(rt);
    }
    else 
    {
        del(ch[rt][1],x);
        pushup(rt);
    }
}
int main(int argc,char *argv[])
{
    freopen("water.in","r",stdin);
    freopen("water.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d%d",&card[i].x,&card[i].y),card[i].opt=1;
    for(int i=n+1;i<=n<<1;++i) scanf("%d%d",&card[i].x,&card[i].y),card[i].opt=2;
    sort(card+1,card+1+n*2);
    for(int i=1;i<=n<<1;++i)
    {
        if(card[i].opt==2) ins(root,card[i].y);
        else 
        {
            if(!cn) continue;
            int v=ask_pre(root,card[i].y);
            if(v==0x7fffffff) continue;
            ans++;
            del(root,v);
        }
    }
    printf("%d\n",ans);
    fclose(stdin); fclose(stdout);
    return 0;
}
splay
技术分享
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
int n;
multiset <int> s;
struct node {int x,y;} a[100005],b[100005];
int cmp(node i,node j) {return i.x<j.x;}
int main()
{
    freopen("water.in","r",stdin);
    freopen("water.out","w",stdout);
    int T;
    T=1;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
        for(int i=0;i<n;i++) scanf("%d%d",&b[i].x,&b[i].y);
        sort(a,a+n,cmp);
        sort(b,b+n,cmp);
        s.clear();
        int k=0,ans=0;
        for(int i=0;i<n;i++)
        {
            while(a[i].x>=b[k].x&&k<n)
            {
                 s.insert(b[k].y);
                 k++;
            }
            if(s.empty())continue;
            multiset<int>::iterator it=s.upper_bound(a[i].y);
            if (it==s.begin()) continue; it--;
            ans++; s.erase(it);
        }
        printf("%d\n",ans);
    }
    return 0;
}
multiset

 

T2

最少需要 log(n)/log(2) 个

dp[j][k] 表示 金币和是 j 最大金币是k 的方案总数

枚举下一枚金币是什么 

技术分享
#include <cstdio>
#include <cmath>
#define N 1005

inline int min(int a,int b) {return a>b?b:a;}
int n,s,ans,f[N][N],dp[N][N];
int main(int argc,char *argv[])
{
    freopen("dream.in","r",stdin);
    freopen("dream.out","w",stdout);
    scanf("%d",&n);
    s=log2(n)+1;
    f[1][1]=1;
    for(int i=1;i<s;++i)
    {
        for(int j=1;j<=n;++j)
         for(int k=1;k<=n;++k)
          if(f[j][k])
           for(int l=k+1;l<=j+1;++l)
            dp[min(n,j+l)][l]+=f[j][k];
        for(int j=1;j<=n;++j)
         for(int k=1;k<=n;++k)
          f[j][k]=dp[j][k],dp[j][k]=0;
    }
    for(int i=1;i<=n;++i) ans+=f[n][i];
    printf("%d %d\n",s,ans);
    fclose(stdin); 
    fclose(stdout);
    return 0;
}
View Code


T3

dp[i][j] 表示 1~i 切了j刀的最优解 

dp[i][j]=min{dp[k][j-1]+sum(k+1,i)}

从大到小 枚举k 更新sum

复杂度 20*N^2

固定j,随着i的增大,k不会减少

1d1d动态规划优化 

20*n^2的简单dp  ->  在固定j的情况下 随着i的增大,k不降  ->  分治求dp值

技术分享
#include <cstdio>
#define N 100005
typedef long long LL;
int n,k,L,R,a[N],s[N];
LL sum,f[N],g[N];
void update(int x,int type)
{
    if(type==1) sum+=s[a[x]],++s[a[x]];
    else --s[a[x]],sum-=s[a[x]];
}
void move(int l,int r)
{
    while(l<L) update(--L,1);
    while(r>R) update(++R,1);
    while(l>L) update(L++,0);
    while(r<R) update(R--,0);
}
void work(int l,int r,int fl,int fr)
{
    if(fl>fr) return;
    int mid=(fl+fr)>>1,mi;
    LL mx=1LL<<60;
    for(int i=l;i<mid&&i<=r;++i)
    {
        move(i+1,mid);
        if(mx>f[i]+sum) mx=f[i]+sum,mi=i;
    }
    g[mid]=mx;
    work(l,mi,fl,mid-1);
    work(mi,r,mid+1,fr);
}
int main(int argc,char *argv[])
{
    freopen("dp.in","r",stdin);
    freopen("dp.out","w",stdout);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    f[0]=0;
    for(int i=1;i<=n;++i) f[i]=1LL<<60;
    while(k--)
    {
        L=1,R=0,sum=0;
        for(int i=1;i<=n;++i) s[i]=0;
        work(0,n-1,1,n);
        for(int i=0;i<=n;++i) f[i]=g[i],g[i]=0;
    }
    printf("%I64d\n",f[n]);
    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

 

以上是关于2017.10.28 QB模拟赛 —— 下午的主要内容,如果未能解决你的问题,请参考以下文章

2017-10-28-morning-清北模拟赛

2017-10-28 noip模拟赛by WISCO 信息组

QuickBlox QB.chat.connect 突然给出令人费解的身份验证错误代码 401

2017.10.28

noip模拟题 2017.10.28 -kmp -Tarjan -鬼畜的优化

北京 2017.10.28 北京 Go & Ruby 活动报名中