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

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

时间: 2024-08-03 14:38:51

2017.10.28 QB模拟赛 —— 下午的相关文章

2017.10.28 QB模拟赛 ——上午

题目链接 T1 1e18 内的立方数有 1e6个 直接枚举可过 二分最优 考场用set  死慢.. #include <cstdio> int t; long long p; int main(int argc,char *argv[]) { freopen("cubic.in","r",stdin); freopen("cubic.out","w",stdout); scanf("%d",&a

2017.6.11 校内模拟赛

题面及数据及std(有本人的也有原来的) :2017.6.11 校内模拟赛 T1 自己在纸上模拟一下后就会发现 可以用栈来搞一搞事情 受了上次zsq 讲的双栈排序的启发.. 具体就是将原盘子大小copy一下排个序 用两个指针维护两个数组(原数据 和 排序后的数据), 即分为1数据和2数组 将小于1指针指向的数据的2数组中的数据全部压入栈中 后进行消除, 将栈栈顶元素与当前1数组中的1指针指向的元素进行比较 相同则消除 后重复过程 直至指针超过N 后判断一下是否两个指针都超过了N... #incl

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=

2017 9 11 noip模拟赛T2

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205; int map[N][N]; int d[N],tag[N],book[N],f[N]; int n,m; void work(int x) { memset(d,63,sizeof(d)); memset(book,0,sizeof(book)); memset(f,0,sizeof(

2018.3.10 省选模拟赛

从这里开始 概况 Problem A 三元组 Problem B 攻略 Problem C 迂回 概况 这是省选T1合集?还是欢乐AK赛? 全班一半以上的人三道题都会做qwq. Doggu还剩一小时时以为自己AK了,然后玩了一小时.虽然最终被卡了20分的常数. ZJC 1个半小时AK?Excuse me? 我这条大咸鱼到最后10分钟才敲完了T1,然后发现线段树要T掉. 发自内心鄙视垃圾出题人卡常数,本来的欢乐AK变成280. 教练给我们考4个小时的试,题面上也这么写的,看题解,woc,考试时间3

2016.10.30 NOIP模拟赛 day2 PM 整理

满分:300分 直接全部爆零,真的是很坑啊! 10.30的题目+数据:链接:http://pan.baidu.com/s/1jHXLace 密码:i784 T1: 题目中的难点就是每次折叠的点可能应经被覆盖了,我的做法是递归去推出它现在在哪个位置,不仅超时,而且答案错误. 也曾想过用数组去存下它当前的位置,但是被10^18的数据吓到了. 正解:并不是所有的坐标都有用,仅仅是那m个将要用到的点有用,所以每次折叠,就只对之后的有用的k个点进行更新,这样就行了. 时间复杂度O(m^2) 不会超时的.

2016.10.30 NOIP模拟赛 day2 AM 整理

题目+数据:链接:http://pan.baidu.com/s/1gfBg4h1 密码:ho7o 总共得了:130分, 1:100分  2:30分(只会这30分的暴力) 3:0(毫无思路) 虽然不高,但是比较满意,因为把自己会的分数都拿到了. T1:100分 1 /* 2 T1明显是个数论题. 3 正确的思路:把n!质因数分解,把所有质因数的指数都取到最大的偶数,它们的乘积便是最终的结果. 4 有一种很快的方法在Eular筛中可以n!的质因数分解. 5 if(!is_prim[i]) 6 { 7

2017 11.6 NOIP模拟赛

1.数学老师的报复(attack.pas/c/cpp)[问题描述]11 班数学大佬 YXN 又在上数学课的时候把班主任 MP6 的错误当众挑出来了,MP6 再一次感到很难堪,于是决定报复 YXNMP6 对 YXN 说:给你一个函数 f(x),定义如下:f ( 1 ) = 1f ( 2 ) = 1f ( n ) = ( A * f ( n - 1 ) + B * f ( n - 2 ) ) mod 7.YXN 说这还不简单,可以秒杀!MP6 微微笑了笑说:n 等于 100 你算得出来,那 n 等于

2016.10.29 NOIP模拟赛 PM 考试整理

300分的题,只得了第三题的100分. 题目+数据:链接:http://pan.baidu.com/s/1o7P4YXs 密码:4how T1:这道题真的是跪在游戏玩少了. 我忽视了游戏中的两个常识:1.开始的序列是无法消除的(这与题目描述明显不符啊),即使有很多可以连消的,而我的程序每次只在插入的位置向两侧寻找可以消除的,自然就错了. 2.开始时的序列居然可以为空,真是让人措手不及! 正确做法:用指针链表,而且不可以用数组模拟.