csp-s模拟测试103「game,time」

time

题解

贪心考虑,考试时想错了,我想的是移动最大值,枚举最大值位置,然后把左面和右面逆序对拼起来,

当然,处理不了有多个最大值情况,于是我就想着打个部分分吧

然而对拍还是挂,

枚举最大值位置是不对的

考虑一种情况a,b,c,d,e,f,g

其中d最大可能出现a移动到d右面更优,b,c留在左面,我只移动最大值的话默认a,b,c都在左面

附赠一组点4 5 2 3 1 6 7 最优决策是6步,方案是2 4 5 6 7 3 1 .

出现了我说的这种情况

考试时打这个题花费时间还是过于多了

正解是贪心移动最小值,这样是保证正确的,只移动最大值相当与限制了一些情况出现

然后最小值考虑了所有情况且一定正确

正难则反__by yangguangjie

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 111111
ll p[A],a[A],b[A],c1[A],c2[A];
ll n,ans=0;
vector <ll> v[A];
//正
void add1(ll x,ll d){for(ll i=x;i!=0&&i<=100000;i+=i&-i) c1[i]+=d;}
ll ask1(ll x,ll ans=0){for(ll i=x;i>=1;i-=i&-i) ans+=c1[i];return ans;}
//逆
void add2(ll x,ll d){for(ll i=x;i>=1;i-=i&-i) c2[i]+=d;}
ll ask2(ll x,ll ans=0){for(ll i=x;i!=0&&i<=100000;i+=i&-i) ans+=c2[i];return ans;}
void sol(){
    for(ll i=1;i<=n;i++){
        add1(i,1);add2(i,1);
        v[a[i]].push_back(i);
    }
    for(ll i=1;i<=100000;i++){
        if(v[i].size()){
            for(ll fr=0,ba=v[i].size()-1;fr<=ba;){
                ll x=v[i][fr],y=v[i][ba];
                ll l=ask1(x-1),r=ask2(y+1);
//                printf("l=%lld r=%lld\n",l,r);
                if(l<r){
                    ans+=l;
                    add1(x,-1);
                    add2(x,-1);
                    fr++;
                }
                else {
                    ans+=r;
                    add1(y,-1);
                    add2(y,-1);
                    ba--;
                }
            }
        }
    }
}
int main(){
    freopen("time.in","r",stdin);
    freopen("time.out","w",stdout);
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++)
        scanf("%lld",&a[i]),p[i]=i;
    sol();
    printf("%lld\n",ans);
}

game

题解

做过一个类似的题(老司机的狂欢),也是求字典序最小,也是第一问特别简单,然后根据第一问推第二问

但实在没想到可以每一位上二分求字典序最小

推单调性

如果upper_bound有值具有单调性,当前选的值越大,以后高的可能性就越小

如果upper_bound没值具有单调性,当前选的值越大,以后得分高的可能越小

但是函数是分段的

可以分两次二分

这样每次set暴力check复杂度$n^2*{log}^2$

现在思考如何check

可以用权值线段树维护

维护A的没用上的牌

维护B的没用上的牌

向上合并时右子树每一张A都可以于左子树中B匹配

代码大致是这样

void up(ll x){
    ll de=min(tr[x<<1|1].L,tr[x<<1].R);
    tr[x].s=tr[x<<1].s+tr[x<<1|1].s+de;
    tr[x].L=tr[x<<1].L+tr[x<<1|1].L-de;
    tr[x].R=tr[x<<1].R+tr[x<<1|1].R-de;
}

代码

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define A 1010100
#define maxx 100000
ll read(){ll x;scanf("%d",&x);return x;}
ll tot,n;
ll b[A],a[A];
multiset<ll> st;
multiset<ll> ::iterator it;
struct node{
    ll l,r,L,R,s;
//L:A的牌
//R:B的牌
//s得分
}tr[A];
void built(ll x,ll l,ll r){
    tr[x].l=l,tr[x].r=r;
    if(l==r){
        return ;
    }
    ll mid=(l+r)>>1;
    built(x<<1,l,mid);
    built(x<<1|1,mid+1,r);
}
void up(ll x){
    ll de=min(tr[x<<1|1].L,tr[x<<1].R);
    tr[x].s=tr[x<<1].s+tr[x<<1|1].s+de;
    tr[x].L=tr[x<<1].L+tr[x<<1|1].L-de;
    tr[x].R=tr[x<<1].R+tr[x<<1|1].R-de;
}
void insert(ll x,ll pla,ll vala,ll valb){
    if(tr[x].l==tr[x].r){
        tr[x].L+=vala;
        tr[x].R+=valb;
        return ;
    }
    ll mid=(tr[x].l+tr[x].r)>>1;
    if(mid>=pla) insert(x<<1,pla,vala,valb);
    else insert(x<<1|1,pla,vala,valb);
    up(x);
}
void getans(ll now){
    insert(1,b[now],0,-1);
    ll l=b[now]+1,r=*st.rbegin(),ans=0;
    while(l<=r){
        ll mid=(l+r)>>1;
        insert(1,mid,-1,0);
        if(tr[1].s+1==tot){
            l=mid+1;
            ans=mid;
        }
        else r=mid-1;
        insert(1,mid,1,0);
    }
    insert(1,ans,-1,0);
    if(tr[1].s+1==tot){
        tot--;
        printf("%d ",ans);
        it=st.find(ans);
        st.erase(it);
        return ;
    }
    insert(1,ans,1,0);
    l=1,r=b[now],ans=0;
    while(l<=r){
        ll mid=(l+r)>>1;
        insert(1,mid,-1,0);
        if(tr[1].s==tot){
            l=mid+1;
            ans=mid;
        }
        else r=mid-1;
        insert(1,mid,1,0);
    }
    insert(1,ans,-1,0);
    printf("%d ",ans);
    it=st.find(ans);
    st.erase(it);
}
int main(){
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    n=read();
    built(1,1,maxx);
    for(ll i=1;i<=n;i++){
        b[i]=read();
        insert(1,b[i],0,1);
    }
    for(ll i=1;i<=n;i++){
        a[i]=read();
        insert(1,a[i],1,0);
        st.insert(a[i]);
    }
    tot=tr[1].s;
    for(ll i=1;i<=n;i++){
        getans(i);
    }
}

原文地址:https://www.cnblogs.com/znsbc-13/p/11809808.html

时间: 2024-08-30 17:18:25

csp-s模拟测试103「game,time」的相关文章

csp-s模拟测试41「夜莺与玫瑰&#183;玫瑰花精&#183;影子」

夜莺与玫瑰 题解 联赛$T1$莫比乌斯$\%\%\%$ $dead$  $line$是直线 首先横竖就是$n+m$这比较显然 枚举方向向量 首先我们枚举方向向量时只枚举右下方向,显然贡献$*2$就是所有斜着的直线 $i,j$表示当自己向右$i$个单位长度,向下$j$单位长度 我们相同斜率下只算最短的线贡献,(因为其他长度下方案数都包含在最短里面了) 我们方向向量$i$,$j$的$gcd(i,j)==1$时我们枚举的才是当前斜率最短长度, 然后考虑贡献 考虑容斥,先算出来当前长度下所有线段再减去重

csp-s模拟测试58「Divisors」&#183;「Market」&#183;「Dash Speed」?

A. Divisors 大概平均下来每个数也就几千约数吧....,直接筛 B. Market 可以把时间离线下来, 考试没有想到将询问离线,用数组存算了算只能过200的点,拿了70 事实上背包后直接二分就好... C. Dash Speed 好题,想到以前的一道题影子. 考场用单调队列多QJ了20分,然而没有想到并查集 线段树上分治????? 线段树上的节点表示在该权值在该区间内的边,每个节点开个vector即可 那么考虑区间查询和单点修改, 对于每个叶子节点,我们从上到下所经历的边其实就是可行

csp-s模拟测试94「凉宫春日的犹豫&#183;漫无止境的八月&#183;射手座之日」

凉宫春日的犹豫 题解 第一次秒切题,5分钟切掉 比较$x^y$和$y!$大小 如果$x^y<y!$输出Yes 问题转化为 $\frac{1}{x} *\frac{2}{x}*\frac{3}{x},,,,,*\frac{y}{x}>=1$输出$Yes$ 开双端队列维护,一直保持单调,然后让队首*队尾就行了 代码 #include<bits/stdc++.h> using namespace std; #define ll long long #define A 111111 lon

微信在线信息模拟测试工具(基于Senparc.Weixin.MP)

目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具. 测试工具在线DEMO:http://weixin.senparc.com/SimulateTool Senparc.Weixin.MP是一个开源的微信SDK项目,地址:https://github.com/JeffreySu/WeiXinMPSDK (其中https://github.com/Jeffrey

noip模拟测试11

T1:string 第一眼秒出思路,这不就是排序那道题的加强版吗? 然而歪?解复杂度虽然是对的,但常数过大,竟被卡到70 歪?解:(实际上std写的就是这个,但据说std被卡掉了 OAO) 因为字符集很小,所以我们可以把区间排序改为区间查询和覆盖 即:先查询区间内所有字符的个数,再从左端点开始按照大小关系依次将长度为字符个数的区间修改为该字符. 期望复杂度O ( 26*mlogn ),实际复杂度O ( 26*mlogn*(巨大的常数) ) 所以需要一(feng)定(kuang)的卡常 正?解:

模拟测试(vj)

做这份模拟测试,已经崩溃了,英文看不懂,题意理解错.到结束了只a了第一题,人生陷入了低谷,于是花了一天的时间终于把不会的弄明白了,在这里写一份总结~ T1,简单的模拟,如果打枪打中一支鸟,将这个位置设为0,并向两边扩散,注意这个位置一定要有鸟. 代码~ #include<bits/stdc++.h> using namespace std; int a[30000]; int n,m; int main() { cin>>n; for(int i=1;i<=n;i++) ci

Android单元测试与模拟测试详解

测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabricator differential 发diff时提交需要执行的单元测试,在开发流程上就可以保证远端代码的稳定性). 2. 测什么? 一般单元测试: 列出想要测试覆盖的异常情况,进行验证. 性能测试. 模拟测试: 根据需求,测试用户真正在使用过程中,界面的反馈与显示以及一些依赖系统架构的组件的应用测

css Hack,用IE11模拟测试的,条件注释要找真IE去测,模拟的无效

<!DOCTYPE html> <!--[if lt IE 7 ]> <html class="ie6 ie"> <![endif]--> <!--[if IE 7 ]> <html class="ie7 ie"> <![endif]--> <!--[if IE 8 ]> <html class="ie8 ie"> <![endif]

2016年上半年软考真题在线模拟测试,提前知晓你的成绩

2016年上半年软考于5月21日结束了,考试完想知道结果的急切心理,几乎每个经历过上学时代的人都能深刻体验到.如果你想知道你考的怎么样,如果你想要提前知道你的成绩,如果你想知道你哪个地方出错了,如果你想知道你哪个地方知识掌握的不够想要更深入的去理解,那就来希赛软考学院吧!希赛软考学院提供2016年上半年软考真题在线模拟测试,有标准的参考答案,有专业老师的解析视频,让你提前知晓你的成绩,让你再次巩固学习. 希赛授课专家介绍 张友生,计算机应用技术博士,软考培训教程系列丛书主编,考试指定教材<系统分