首页 > 其他分享 >CSP 模拟 3

CSP 模拟 3

时间:2023-07-23 16:33:23浏览次数:35  
标签:int gonna -- black long CSP 模拟 define

今天感觉很热,但是天气转凉的时候我也该退役了吧。

今日推歌:

透明哀歌 - n-buna / Gumi
echo - Crusher-P / Gumi English

歌词 The clock stopped ticking,时钟停止发出嘀嗒声

Forever ago.在很久以前

How long have I been up?我究竟醒来了多久?

I don't know.我不知道

I can't get a grip,我无法紧紧抓住

But I can't let go却也无法放手

There wasn't anything(虽然如此)却没有任何东西

To hold on to though...让我紧紧抓住...

Why can't I see?为何我看不见?

Why can't I see?为何我看不见?

All the colors that you see?你所看到的全部色彩?

Please, Can I be,请问,我能变得

Please, Can I be请问,我能够变得

Colorful and free?色彩斑斓和自由吗?

WHAT THE HELL'S GOING ON?!究竟发生了什么事?!

CAN SOMEONE TELL ME PLEASE--求求你,谁能告诉我--

WHY, I'M SWITCHING FASTER THAN THE CHANNELS ON TV!!为何我切换得比电视上的频道还要快!!

I'M black, THEN I'M white!!我是黑色,然后我是白色!!

NO!!!不!!!

SOMETHING ISN'T RIGHT!!有什么不对劲!!

MY ENEMY'S INVISIBLE, I DON'T KNOW HOW TO FIGHT!!我的敌人是透明的,我不知道如何去战斗!!

THE TREMBLING FEAR IS MORE THAN I CAN TAKE,颤栗着的恐惧已经超出我的承受能力

WHEN I'M UP AGAINST当我与镜子里的

THE ECHO IN THE MIRROR!!回声对抗!!

ECHO!!回声!!

I'm gonna burn my house down,我会把我的房子烧成,

Into an ugly black.一片丑陋的黑色。

I'm gonna run away, Now我现在就会逃跑

And never look back.然后再也不回头

I'm gonna burn my house down,我会把我的房子烧成

Into an ugly black.丑陋的黑色

I'm gonna run away, Now我现在就要逃跑

And never look back.然后再也不回头

I'm gonna burn my house down,我现在就要把我的房子烧成

Into an ugly black.丑陋的黑色

I'm gonna run away, Now我现在就要逃跑

And never look back.然后再也不回头

I'm gonna burn my house down,我现在就要把我的房子烧成

Into an ugly black.丑陋的黑色

I'm gonna run away, Now我现在就要逃跑

And never look back.然后再也不回头

I'm gonna burn my house down,我现在就要把我的房子烧毁,

Into an ugly black.丑陋的黑色

I'm gonna run away, Now我现在就要逃跑

AND NEVER LOOK BACK!!然后再也不回头!!

WHAT THE HELL'S GOING ON?!究竟是怎么回事?!

CAN SOMEONE TELL ME PLEASE--求求你,告诉我好吗--

WHY, I'M SWITCHING FASTER THAN THE CHANNELS ON TV!!为何我切换得比电视频道都要快

I'M black, THEN I'M white!!我是黑色 而后变成白色

NO!!!不!!!SOMETHING ISN'T RIGHT!!有什么不对劲!!

MY ENEMY'S INVISIBLE, I DON'T KNOW HOW TO FIGHT!!我的敌人是无形的,我不知道要如何去战斗!!

WHAT THE HELL'S GOING ON?!究竟是怎么回事?!

CAN SOMEONE TELL ME PLEASE--求求你,谁能告诉我--

WHY, I'M SWITCHING FASTER THAN THE CHANNELS ON TV!!为何我切换得比电视上的频道还要快!!

I'M black, THEN I'M white!!我是黑色,然后我是白色!!

NO!!!不!!!

SOMETHING ISN'T RIGHT!!有什么不对劲!!

MY ENEMY'S INVISIBLE, I DON'T KNOW HOW TO FIGHT!!我的敌人是透明的,我不知道要如何去战斗

THE TREMBLING FEAR IS MORE THAN I CAN TAKE,颤栗着的恐惧已超出我的承受能力

WHEN I'M UP AGAINST当我与镜子里的

THE ECHO IN THE MIRROR!!回声对抗!!

THE TREMBLING FEAR IS MORE THAN I CAN TAKE,颤栗着的恐惧已超出我的承受能力,

WHEN I'M UP AGAINST当我与镜子里的

THE ECHO IN THE MIRROR!!回声对抗!!

T1 回文

简单题,但是赛时就是死活想不到,因为走的步数是固定的,所以同时从起点和终点走,枚举从起点和终点分别走到哪里,因为一共走的步数是一定的,所以可以把四个状态化成三个状态,然后大力 dp 即可

这题有点卡常+卡空间,在这之前我都不敢想 \(O(n^3)\) 时空复杂度过 500

点击查看代码
#include<bits/stdc++.h>
// #define int long long
#define N 505
using namespace std;

const int p=993244853;
int n,m,f[N][N][N];
long long ans;
char s[N][N];

signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        scanf("%s",s[i]+1);
    f[1][1][n]=(s[1][1]==s[n][m]);
    if(!f[1][1][n]){
        printf("0\n");
        return 0;
    }
    for(int x1=1;x1<=n;x1++)
        for(int y1=1;y1<=m;y1++)
            for(int x2=min(n,n+m+2-x1-y1);x2>=x1&&n+m+2-x1-y1-x2<=m;x2--){
                int y2=n+m+2-x1-y1-x2;
                if(s[x1][y1]==s[x2][y2]) f[x1][y1][x2]=((long long)f[x1][y1][x2]+f[x1-1][y1][x2+1]+f[x1-1][y1][x2]+f[x1][y1-1][x2+1]+f[x1][y1-1][x2])%p;
            }
    for(int x1=1;x1<=n;x1++)
        for(int y1=1;y1<=m;y1++){
            int x2=x1,y2=y1; 
            if(x1+x2+y1+y2==n+m+2) ans+=f[x1][y1][x2];
            x2=x1+1,y2=y1;
            if(x1+x2+y1+y2==n+m+2) ans+=f[x1][y1][x2];
            x2=x1,y2=y1+1;
            if(x1+x2+y1+y2==n+m+2) ans+=f[x1][y1][x2];
            ans%=p;
        }
    cout<<ans;
}

T2 快速排序

简单题,不难发现,只有正常数字才会参与排序,然后每个数字会将所有还没被移动比自己小的的数字按顺序放到自己后边,只要将所有数字存下来排序然后跑一遍即可

点击查看代码
#include<bits/stdc++.h>
#define N 500005
using namespace std;

int T,n,top,stk[N];
struct number{
	bool isnan;
	int value;
}A[N];
bool operator < (const number& x, const number& y){
	if(x.isnan || y.isnan) return false;
	return x.value < y.value;
}

int main(){
    // freopen("qsort2.in","r",stdin);
    // freopen("qsort.out","w",stdout);
    cin>>T;
    while(T-->0){
        scanf("%d",&n);
        int flag=true;top=0;
        for(int i=1;i<=n;i++){
            char tmp[15];
            scanf("%s",tmp+1);
            A[i].isnan=(tmp[1]=='n');
            if(A[i].isnan) continue;
            int len=strlen(tmp+1);
            for(int j=1;j<=len;j++)
                A[i].value=A[i].value*10+(tmp[j]-'0');
            stk[++top]=A[i].value;
        }
        sort(stk+1,stk+1+top);
        int lst=1,maxn=0;
        for(int i=1;i<=n;i++){
            if(A[i].isnan) printf("nan ");
            else{
                if(maxn<=A[i].value){
                    int now=lower_bound(stk+lst,stk+top+1,A[i].value)-stk;
                    for(int j=lst;j<=now;j++) printf("%d ",stk[j]);
                    lst=now+1;
                }
                maxn=max(A[i].value,maxn);
            }
            A[i].value=0;
        }
        printf("\n");
    }
}

T3 混乱邪恶

构造,先将 \(a\) 升序排序,然后设 \(d_i=a_{2i}-a_{2i-1}\)

然后按如下方案构造:

重复进行如下操作直到 \(n=1\):

  • 取出集合中的 \(\min d\) 和 \(\max d\)
  • 将 $\max d-\min d $ 插入集合中
  • \(n=n-1\)

如果对于一个 \(\{d_n\}\) 来说存在一个 \(\{e_n\}\) 使得 \(\sum d_ie_i=0\),那么构造出 \(\{d_n\}\) 的 \(\{d'_n\}\) 也有一个确定的 \(\{e'_n\}\)

对于 \(n=1\) 的情况,\(e_1=1\) 或者 \(-1\) 都可以,然后对于每个操作来说,建一个新节点表示 \(\max d-\min d\),然后向 \(\min d\) 连一条权值为 \(-1\) 的边,向 \(\max d\) 连一条权值为 \(1\) 的边,对于初始的 \(d_i\) 来说,建一条权值 \(-1\) 的边向 \(2i\),建一条权值 \(1\) 的边向 \(2i-1\),然后从 \(n=1\) 的情况向下走,每个点的取值即为从当前点到根上路径的乘积

点击查看代码
#include<bits/stdc++.h>
#define N 3000005
#define int long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;

int n,m,a[N],c[N],rollingstar;
int tot,tree[N][2],node[N];
int stk[N],top;
multiset<pii> ms;
void solve(int n){
    if(n==1) return;
    auto mx=--ms.end(),mn=ms.begin();
    pii maxn=*mx,minn=*mn;
    ms.erase(mx);ms.erase(mn);
    tree[++tot][0]=maxn.second;
    tree[tot][1]=minn.second;
    // cout<<tot<<" "<<tree[tot][0]<<" "<<tree[tot][1]<<endl;
    ms.insert(mp(maxn.first-minn.first,tot));
    solve(n-1);
}
void dfs(int u,int num);

signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) scanf("%lld",a+i);
    if(n%2) a[++n]=0,rollingstar++;
    for(int i=1;i<=n;i++) c[a[i]]=i;
    sort(a+1,a+1+n);tot=n;
    for(int i=1;i<=n;i+=2){
        tree[++tot][0]=c[a[i+1]],tree[tot][1]=c[a[i]],
        ms.insert(mp(a[i+1]-a[i],tot));
        // cout<<c[a[i]]<<" "<<c[a[i+1]]<<endl;
    }
    solve(n/2);dfs(tot,0);
    printf("NP-Hard solved\n");
    for(int i=1;i<=n-rollingstar;i++) printf("%lld ",node[i]);
}

void dfs(int u,int num){
    // cout<<u<<" "<<node[u]<<endl;
    if(tree[u][0]<=n){
        node[tree[u][0]]=num?-1:1;
        node[tree[u][1]]=num?1:-1;
        return;
    }
    dfs(tree[u][0],num);
    dfs(tree[u][1],num^1);
}

T4 校门外歪脖树上的鸽子

nb ds 题

考虑在原本的树上向右上走的意义为让节点管辖区间的右端点扩张,向左上走的意义类似

将 \([l,r]\) 的操作化为 \(l\) 到 \(\operatorname{lca}(l,r)\) 的操作和 \(r\) 到 \(\operatorname{lca}(l,r)\) 的操作

现在我们只考虑左端点链上的情况

首先我们令 \(u\) 为 \(l\) 节点向右上跳的最远位置,这表示让以 \(l\) 为左端点的区间尽可能的大

特殊情况

如果 \(u\) 是 \(\operatorname{lca}\) 祖先,说明只需要操作 \(\operatorname{lca}\) 的左儿子即可

需要注意的是,如果左右都是这种情况,说明只需要操作 \(\operatorname{lca}\) 即可

\(u\) 是最远位置说明向右上跳不动了,那么左上还能跳,但是如果向左上跳的话说明左端点会扩张,不成立,所以考虑寻找下一个节点,\(u\) 的祖先肯定是不行了,但是 \(u\) 的父亲的兄弟是可行的,所以这是第二个节点,所以就抽象为这条链上所有与 \(l\) 节点同侧但父亲不同侧的节点,其最终会跳到 \(\operatorname{lca}\) 的右儿子,那么我们 dfs 一遍将满足这个关系的节点求出来并连边,操作就化为了这个新树上的树链剖分

写代码的时候复刻了题目的线段树:

void pushdown(int pos,int l,int r){
    if(lz[pos]) return;
    sum[lc]+=(cnt[mid]-cnt[l-1])*lz[pos];
    sum[rc]+=(cnt[r]-cnt[mid])*lz[pos];
    lz[lc]+=lz[pos];
    lz[rc]+=lz[pos];
    lz[pos]=0;
}
点击查看代码
#include<bits/stdc++.h>
#define N 500005
#define int long long 
#define pii pair<int,int>
#define lc (pos<<1)
#define rc ((pos<<1)|1)
#define inf 0x3f3f3f3f
#define mid ((l+r)>>1)
#define mp make_pair
using namespace std;

int head[N],tot,total;
struct edge{
    int v,nxt;
}e[N*2];
inline void add(int u,int v){
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int n,m,tree[N][2],rt,siz[N],Cnt[N],hson[N],top[N],dfn[N];
int dep[N],f[N][21],vis[N],bro[N],fa[N],cnt[N];
void Dfs(int u){ // 原树上 dfs 一遍预处理倍增数组
    for(int i=1;i<=20;i++)
        f[u][i]=f[f[u][i-1]][i-1];
    if(!tree[u][0]) {Cnt[u]=1;return;}
    else{
        f[tree[u][0]][0]=f[tree[u][1]][0]=u;
        dep[tree[u][0]]=dep[tree[u][1]]=dep[u]+1;
        Dfs(tree[u][0]);Dfs(tree[u][1]);
        Cnt[u]=Cnt[tree[u][0]]+Cnt[tree[u][1]];
    }
}
void Dfs1(int u,int top){ // 原树上 dfs 求能跳到右上的最远点的兄弟
    if(!tree[u][0]) return;
    add(tree[u][0],top);add(top,tree[u][0]);
    Dfs1(tree[u][0],top);
    Dfs1(tree[u][1],tree[u][0]);
}
void Dfs2(int u,int top){ // 原树上 dfs 求能跳到左上的最远点的兄弟
    if(!tree[u][0]) return;
    add(tree[u][1],top);add(top,tree[u][1]);
    Dfs2(tree[u][0],tree[u][1]);
    Dfs2(tree[u][1],top);
}
int lca(int x,int y){
    // cout<<"in:"<<x<<" "<<y<<endl;
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;i--){
        if(dep[f[x][i]]>=dep[y]) x=f[x][i];
        if(x==y) return x;
    }
    for(int i=20;i>=0;i--)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    // cout<<"out:"<<x<<" "<<y<<endl; 
    return f[x][0];
}
struct SMT{
    int sum[N<<2],lz[N<<2];
    void pushdown(int pos,int l,int r){
        if(!lz[pos]) return;
        sum[lc]+=(cnt[mid]-cnt[l-1])*lz[pos];
        sum[rc]+=(cnt[r]-cnt[mid])*lz[pos];
        lz[lc]+=lz[pos];
        lz[rc]+=lz[pos];
        lz[pos]=0;
    }
    void update(int pos,int l,int r,int L,int R,int val){
        if(r<L||R<l) return;
        if(L<=l&&r<=R){
            sum[pos]+=(cnt[r]-cnt[l-1])*val;
            lz[pos]+=val;
            return;
        }
        pushdown(pos,l,r);
        update(lc,l,mid,L,R,val);
        update(rc,mid+1,r,L,R,val);
        sum[pos]=sum[lc]+sum[rc];
    }
    int query(int pos,int l,int r,int L,int R){
        // cout<<pos<<" "<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
        if(r<L||R<l) return 0;
        if(L<=l&&r<=R) return sum[pos];
        pushdown(pos,l,r);
        return query(lc,l,mid,L,R)+query(rc,mid+1,r,L,R);
    }
}T;
// 熟练剖分
void dfs1(int u,int p){
    int maxn=0;
    fa[u]=p;siz[u]=1;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(v==p) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(maxn<siz[v]){
            maxn=siz[v];
            hson[u]=v;
        }
    }
}
void dfs2(int u,int anc){
    top[u]=anc;cnt[++total]=Cnt[u];dfn[u]=total;
    if(hson[u]) dfs2(hson[u],anc);
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(v==fa[u]||v==hson[u]) continue;
        dfs2(v,v);
    }
}
void updateChain(int x,int y,int val){
    while(top[x]!=top[y]){
        T.update(1,1,2*n-1,dfn[top[x]],dfn[x],val);
        x=fa[top[x]];
    }
    T.update(1,1,2*n-1,dfn[y],dfn[x],val);
    T.update(1,1,2*n-1,dfn[y],dfn[y],-val);
}
int queryChain(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        // cout<<x<<endl;
        ans+=T.query(1,1,2*n-1,dfn[top[x]],dfn[x]);
        x=fa[top[x]];
    }
    ans+=T.query(1,1,2*n-1,dfn[y],dfn[x]);
    ans-=T.query(1,1,2*n-1,dfn[y],dfn[y]);
    return ans;
}
#define is(u) (tree[f[u][0]][1]==u)
void Update(int l,int r,int val){
    int tmp=lca(l,r);
    if(!is(l)) l=bro[fa[l]];
    if(is(r)) r=bro[fa[r]];
    if(dep[l]<=dep[tmp]&&dep[r]<=dep[tmp]){ T.update(1,1,2*n-1,dfn[tmp],dfn[tmp],val);return;}
    if(dep[l]<=dep[tmp]) T.update(1,1,2*n-1,dfn[tree[tmp][0]],dfn[tree[tmp][0]],val);
    else updateChain(l,tree[tmp][1],val);
    if(dep[r]<=dep[tmp]) T.update(1,1,2*n-1,dfn[tree[tmp][1]],dfn[tree[tmp][1]],val);
    else updateChain(r,tree[tmp][0],val);
}
int Query(int l,int r){
    int tmp=lca(l,r),ans=0;
    if(!is(l)) l=bro[fa[l]];
    if(is(r)) r=bro[fa[r]];
    if(dep[l]<=dep[tmp]&&dep[r]<=dep[tmp]) return T.query(1,1,2*n-1,dfn[tmp],dfn[tmp]);
    if(dep[l]<=dep[tmp]) ans+=T.query(1,1,2*n-1,dfn[tree[tmp][0]],dfn[tree[tmp][0]]);
    else ans+=queryChain(l,tree[tmp][1]);
    if(dep[r]<=dep[tmp]) ans+=T.query(1,1,2*n-1,dfn[tree[tmp][1]],dfn[tree[tmp][1]]);
    else ans+=queryChain(r,tree[tmp][0]);
    return ans;
}

signed main(){
    // freopen("pigeons2.in","r",stdin);
    // freopen("pigeons.out","w",stdout);
    cin>>n>>m;
    for(int i=n+1;i<=2*n-1;i++){
        int Lc,Rc;scanf("%lld%lld",&Lc,&Rc);
        tree[i][0]=Lc;tree[i][1]=Rc;
        vis[Lc]=vis[Rc]=true;
        bro[Lc]=Rc;bro[Rc]=Lc;
    }
    for(int i=n+1;i<n*2;i++) if(!vis[i]) rt=i;
    dep[rt]=1;
    Dfs(rt);Dfs1(rt,rt);Dfs2(rt,rt);
    dfs1(rt,0);dfs2(rt,rt);
    for(int i=1;i<n*2;i++) cnt[i]+=cnt[i-1];
    while(m-->0){
        int op;scanf("%lld",&op);
        if(op==1){
            int l,r,x;
            scanf("%lld%lld%lld",&l,&r,&x);
            Update(l,r,x);
        }
        else{
            int l,r;
            scanf("%lld%lld",&l,&r);
            printf("%lld\n",Query(l,r));
        }
    }
}

标签:int,gonna,--,black,long,CSP,模拟,define
From: https://www.cnblogs.com/Rolling-star/p/17575153.html

相关文章

  • CSP 模拟 2
    感觉像是noi模拟赛多了个pT1F咋做都行,但是考场上的正确做法被后来优化RE了,痛失60pts其中一种做法是考虑只有\(a_1\oplusb_i\)有可能成为答案,然后验证即可T2S定义dp状态\(f_{i,j,k,0/1/2}\)为用了\(i\)个红球,\(j\)个绿球,\(k\)个红球,并且最后一位是什么球......
  • java 爬虫模拟登陆 拿到cookies
    实现Java爬虫模拟登录获取Cookies概述在这篇文章中,我将教你如何使用Java编程语言实现爬虫模拟登录并获取Cookies。爬虫模拟登录是一种常见的网络爬虫技术,它可以模拟用户登录网站,获取登录后才能访问的资源。流程概览下面是整个模拟登录获取Cookies的流程概览:步骤描述......
  • 模拟飞行开发任务进度
    第一周(截止2023.7.23上午)任务主要进度:跟着做的案例为Stack-O-Bot,有官方的文档以及游戏教学过程,比较适合新手进行学习,根据官方给的教学,大体上复现了他的效果。正在学习蓝图类模型,类似于图形化的编程界面?编程的重点是逻辑的设计,需要考虑好每一个过程的关系以及物理过程(这个在......
  • P7074 [CSP-J2020] 方格取数 题解
    题目:题目描述设有n*m 的方格图,每个方格中都有一个整数。现有一只小熊,想从图的左上角走到右下角,每一步只能向上、向下或向右走一格,并且不能重复经过已经走过的方格,也不能走出边界。小熊会取走所有经过的方格中的整数,求它能取到的整数之和的最大值。输入格式第一行有两个整......
  • Qt(5.8.0)-Cmd模拟(纯手写)
    以下是对上述Qt程序的详细博客,使用Markdown的代码块方式呈现:Qt编程:实现一个简单的命令行窗口Qt是一种跨平台的C++应用程序开发框架,可以用于开发各种类型的应用程序,包括图形界面(GUI)应用程序。本文将介绍如何使用Qt框架实现一个简单的命令行窗口,类似于Windows的运行框,用户可以在......
  • 「赛后总结」20230722 CSP 模拟赛
    「赛后总结」20230722CSP模拟赛点击查看目录目录「赛后总结」20230722CSP模拟赛反思题解T1回文思路代码T2快速排序思路代码T3混乱邪恶思路代码T4校门外歪脖树上的鸽子思路吓死我了我还以为K8He不更博了。为啥前天模拟赛不写啊?打过,没参加。为啥昨天模拟赛不......
  • strlen/strcpy/strcat的模拟实现
    char*my_strcat(char*dest,constchar*src){ assert(dest!=NULL);//字符串要以‘\0’结束,目标空间要足够大,且可修改 assert(src!=NULL); char*ret=dest; //1,找到目的字符串的\0; while(*dest!='\0') { dest++; } //2,追加 while(*dest++=*src++) { ; } returnr......
  • CSP模拟3
    A.回文\(20\)多分的纯暴力搜索,\(A_{i,j}=A_{i-1,j+1}\)可以判完回文直接递推出路径数,共\(42\text{pts}\)。正解\(DP\)。回文可以转化一下思路,两个人分别从\((1,1),(n,m)\)出发,走的路径相同的方案数。设计\(dp[i][j][s][t]\)为第一个人在\((i,j)\)位置,第二个人在......
  • [爬虫]2.2.1 使用Selenium库模拟浏览器操作
    Selenium是一个非常强大的工具,用于自动化Web浏览器的操作。它可以模拟真实用户的行为,如点击按钮,填写表单,滚动页面等。由于Selenium可以直接与浏览器交互,所以它可以处理那些需要JavaScript运行的动态网页。安装Selenium首先,我们需要安装Selenium库。你可以使用pip命令来安装:pip......
  • 模拟ArrayList(顺序表)的底层实现
    模拟ArrayLIst的底层实现packagecom.tedu.api04.list;importjava.util.Objects;/***@authorLIGENSEN*Date:2023/7/2011:35*/publicclassArrayListDemo{publicstaticvoidmain(String[]args){ArrList<String>list=newArrList<>......