CSP2020 游记

考前一周

就完全学不太进去文化课了

然后特别想停课但是不行

结果每天翘着作业苟机房,被老师在后面喊打文化课笔记没整呀这样子

Day 0

早上学了一节物理和语文课

(结果考试语文年级 5001 名)

接着拿上了东西就出发了

在去德州的大巴上一直和 An_Fly 聊天

到车站面到了 hzoi2019 和换了发型的 skyh

晚上打了牛客,orz happyguy 1A 下凸包

Day 1

上午学了四毛子算法,颓过了 Loj6499

下午开幕雷击:又是题面非常长的题目,冷静读完发现是大模拟

诶我手动模拟日期我会呀,那咱先写个暴力模拟跳日期

写完之后就发现每四百年有一样的日期,那就开冲,大概写了两个多小时写完了,没测大样例就和暴力拍上来

然后看看这个 T4,这个 n2 很容易啊,搞个 dfs 就行了呀,写完 dfs 之后发现 bool 返回值如何处理自己写之前并没有想清楚

结果 20 跑路了

这时候距离考试结束还有约一小时,然后把T2写上去,但是没发现可以与到一起做,所以复杂度带 log

中间反复确认是不是需要读入 qi,最后决定还是读上,还手写二分代替 lower_bound 来离散化

一贯 #define int long long 的我开了 ull 就走人了显然没注意到 264 的问题

中间发现居然还有 大样例,测了一下过拍的 T1 发现不行???

冷静下来发现答案差 1 天,又改了改就好了

最后读完这个 T3 还剩下 10 分钟,冲了最裸暴力就检查文件跑路了

出场发现有不少人会这个 T3,T2 还得判 264 ,心情瞬间废掉了

不过测了一下 T1 没挂,让心态稳健了一些

出分是 100+95+30+20

技术总结

  • 如果要求 2641 可以写 ull x=-1;

  • 函数调用

    发现这个调用肯定是个 DAG

    按照一些做法就是加法直接跟着后面的乘法做

    那么先统计所有序列里面的乘法量,然后拓扑标记和方案

  • 贪吃蛇

    我们发现这里的最大最小值用 set 维护一下

    然后把所有的蛇吃的情况模拟出来之后逆序扫一下,如果发现不满足的之际把后面的都置空

    那么这样的做法是 O(Tnlogn)

    然后发现后面的扫是不能降复杂度或者得到更好的做法

    那么优化前面求最大最小值的部分


以下参考了 EI 博客

考虑最大值和最小值的改变

如果 an2a1 那么最小值肯定是 min(a2,ana1)

这时候就按照 NOIP2016 蚯蚓的套路来进行维护俩单调队列即可

单调性请自行证明

如果 an2a1 那么就先将已经维护的两个队列归并一下,这部分可以做到 O(n)

因为减掉之后ana1<a2 那么直接成为最小值就行了

不难证明剩下吃的都是小于 a2 的量

如果最后剩下很多值都是a1 但是 id 不同,模拟情况即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define reg register
inline int read(){
    int res=0,f=1; char k;
    while(!isdigit(k=getchar())) if(k=='-') f=-1;
    while(isdigit(k)) res=res*10+k-'0',k=getchar();
    return res*f;
}
const int N=1e6+10;
struct node{
    int v,id;
    bool operator<(const node &a)const{
        if(v^a.v) return v<a.v;
        return id<a.id;
    }
    bool operator ==(const node &a)const{return v==a.v&&id==a.id;}
}p[N],q1[N],q2[N],q3[N];
bool fl[N],vis[N];
int pre[N],n,s1[N],s2[N],cnt,a[N],t1,t2,t3,h1,h2,h3;
inline int size2(){return t2-h2+1;}
inline int size1(){return t1-h1+1;}
inline void EI_method(){
    memset(vis,0,sizeof(vis));
    int mnv=q3[h3].v; vis[q3[h3].id]=1;
    int id=1,fp=1;  while(fp<=t3&&q3[fp].v==mnv) vis[q3[fp].id]=1,++fp;
    while(!vis[id]) ++id; node tmp=(node){-1,-1};
    for(reg int i=t3;i>=fp;--i){
        s2[++cnt]=q3[i].id;
        if(tmp.id!=-1){
            s1[cnt]=tmp.id;
            if((node){q3[i].v-tmp.v,q3[i].id}<(node){mnv,id}) tmp=(node){q3[i].v-tmp.v,q3[i].id};
            else vis[q3[i].id]=1,tmp.id=-1,tmp.v=-1;
        }else{
            s1[cnt]=id; vis[id]=0; 
            while(id<=n&&!vis[id]) ++id; 
            tmp=(node){q3[i].v-mnv,q3[i].id};
        } 
    }
    if(tmp.id!=-1&&tmp.v==mnv){
        id=tmp.id; tmp.id=-1; tmp.v=-1; 
        vis[id]=1;    
    }
    if(tmp.id!=-1){
        for(reg int i=n;i>=1;--i){
            if(vis[i]) s1[++cnt]=tmp.id,s2[cnt]=i,tmp.id=i;
        }
    }else{
        for(reg int i=n,cur=0;i>=1;--i){
            if(!vis[i]) continue; cur^=1;
            if(cur){
                if(tmp.id!=-1) s1[++cnt]=tmp.id,s2[cnt]=i; 
                tmp.id=i; 
            }else s1[++cnt]=i,s2[cnt]=tmp.id; 
        }
    }return ;
}
inline void work(){
    h1=1; t2=n; h2=n+1; t1=0; cnt=0;
    memset(fl,0,sizeof(fl));
    for(reg int i=1;i<=n;++i) q1[++t1]=p[i]=(node){a[i],i};
    for(reg int i=1;i<=n;++i){
        node mx=(node){-1,-1},mn=(node){9e18+10,9e18+10};
        if(size1()) mx=max(mx,q1[t1]),mn=min(mn,q1[h1]);
        if(size2()) mx=max(mx,q2[t2]),mn=min(mn,q2[h2]);
        if(mx.v<mn.v*2){
            h3=1; t3=0; 
            while(size1()&&size2()){
                if(q1[h1]<q2[h2]) q3[++t3]=q1[h1++];
                else q3[++t3]=q2[h2++];
            } 
            while(size1()) q3[++t3]=q1[h1++];
            while(size2()) q3[++t3]=q2[h2++];
            EI_method();
            break;
        }else{
            s1[++cnt]=mn.id; s2[cnt]=mx.id;
            if(size2()&&mx==q2[t2]) t2--; else t1--;
            if(size2()&&mn==q2[h2]) h2++; else h1++;
            q2[--h2]=(node){mx.v-mn.v,mx.id};
        } 
    }
    int las=n; 
    for(reg int i=1;i<=n-1;++i) fl[s1[i]]=1;
	for(reg int i=n-1;i>=1;--i){
		if(fl[s2[i]]){
			while(las>i) fl[s1[--las]]=0;
		} 
	}printf("%lld\n",n-las+1); 
	return ;
}
signed main(){
    int T=read(); T--;
    n=read(); for(reg int i=1;i<=n;++i) a[i]=read(); work();
    while(T--){
        int pos,v,siz=read();
        while(siz--) pos=read(),v=read(),a[pos]=v;
        work();
    } return 0;
}```
posted @   没学完四大礼包不改名  阅读(258)  评论(3编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示