首页 > 其他分享 >儿童节,GDKOI2024普及组

儿童节,GDKOI2024普及组

时间:2024-06-01 15:54:53浏览次数:28  
标签:GDKOI2024 普及 minn int 儿童节 tr 拓展 fa include

儿童节快乐捏

捉迷藏

Zayin和Ziyin在一棵\(n\)个节点的树上,Zayin从\(a\)节点开始,每次可以走\(da\)步,Ziyin从\(b\)节点开始,每次可以走\(db\)步,走到了另一个人所在的节点的人获胜。求在最优策略下,两者谁会获胜。

题解:

令\(a\)和\(b\)之间的距离是\(dis\)

简单易得

当\(dis<da\)时,Zayin胜

否则,当\(da>db\)时,Zayin胜

否则,当\(da=db\)时,平局

否则,当\(da<db\)时,Ziyin胜

其中\(dis\)使用倍增求\(lca\)求解

代码

#include<cstdio>
#include<cstring>
const int N=1000005;
int n,head[N],pedge,dep[N],fa[N][22],t,q;
struct Edge{
    int to,next;
}edge[N<<1];
inline void Ins(int u,int v){edge[++pedge]={v,head[u]},head[u]=pedge;}
inline void ins(int u,int v){Ins(u,v),Ins(v,u);}
inline void swap(int&x,int&y){x^=y^=x^=y;}
void prework(int u,int father){
    fa[u][0]=father,dep[u]=dep[father]+1;
    for(int i=1;1<<i<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int e=head[u];e;e=edge[e].next){
        int v=edge[e].to;
        if(v^father)prework(v,u);
    }
}
inline int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    for(int i=20;~i;i--)if(dep[fa[u][i]]>=dep[v])u=fa[u][i];
    if(u==v)return u;
    for(int i=20;~i;i--)if(fa[u][i]^fa[v][i])u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}
int main(){
    for(scanf("%*d%d",&t);t--;){
        scanf("%d%d",&n,&q),memset(head+1,0,n<<2);
        for(int i=1;i<=n;i++)memset(fa[i],0,84);
        for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),ins(u,v);
        prework(1,0);
        for(int a,b,da,db,dis;q--;){
            scanf("%d%d%d%d",&a,&b,&da,&db),dis=dep[a]+dep[b]-dep[lca(a,b)]*2;
            if(dis<=da||da>db)puts("Zayin");
            else if(da<db)puts("Ziyin");
            else puts("Draw");
        }
    }
    return 0;
}

读书

题面:

每次读书的第\(i\)个章节,都需要至少已经阅读其他的\(a_i\)个章节,每天从头到尾读书,把能读的章节读了,最少需要几天,读不完输出\(-1\)。

题解:

每天内读书相当与找一个最小值\(min\),若\(min\le0\)那么可以读书并将其后面的\(a_i\)全部减\(1\),将这个\(a_i\)赋值成\(\infty\),在没有\(min\le0\)后,把每个设置成\(\infty\)的数前面也减去\(1\)并进入下一天。

如果\(n\)天结束还没有读完书,那么就读不完了。

使用线段树维护区间加最小值。

代码

#include<cstdio>
const int N=500005,INF=0x3f3f3f3f;
int n,a[N],tot,stk[N],top;
struct Tree{
    int l,r,minn,pos,tag;
}tr[N<<2];
inline int min(int x,int y){return x<y?x:y;}
inline int ls(int u){return u<<1;}
inline int rs(int u){return u<<1|1;}
inline void pushup(int u){
    if(tr[ls(u)].minn>tr[rs(u)].minn)tr[u].minn=tr[rs(u)].minn,tr[u].pos=tr[rs(u)].pos;
    else tr[u].minn=tr[ls(u)].minn,tr[u].pos=tr[ls(u)].pos;
}
inline void push(int u,int x){
    tr[u].minn+=x,tr[u].tag+=x;
}
inline void pushdown(int u){
    if(tr[u].tag)push(ls(u),tr[u].tag),push(rs(u),tr[u].tag),tr[u].tag=0;
}
void build(int u,int l,int r){
    tr[u].l=l,tr[u].r=r;
    if(l==r)return tr[u].minn=a[l],tr[u].pos=l,void();
    int mid=(l+r)>>1;
    build(ls(u),l,mid),build(rs(u),mid+1,r),pushup(u);
}
void modify(int u,int l,int r,int x){
    if(l<=tr[u].l&&r>=tr[u].r)return push(u,x);
    int mid=(tr[u].l+tr[u].r)>>1;
    pushdown(u);
    if(l<=mid)modify(ls(u),l,r,x);
    if(r>mid)modify(rs(u),l,r,x);
    pushup(u);
}
int main(){
    scanf("%*d%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",a+i);
    build(1,1,n);
    for(int i=1;i<=n+1;modify(1,1,n,-top),top=0,i++){
        if(i==n+1){
            puts("-1");
            break;
        }
        for(;tr[1].minn<=0;){
            int p=tr[1].pos;
            if(p^n)modify(1,p+1,n,-1);
            modify(1,p,p,INF),stk[++top]=p,tot++;
            if(tot==n)break;
        }
        if(tot==n){
            printf("%d\n",i);
            break;
        }
        for(int i=1;i<=top;i++)if(stk[i]^n)modify(1,stk[i]+1,n,1);
    }
    return 0;
}

正方形拓展

每个点会按正方形拓展,两个图形相遇后不再拓展,有\(n\)个起始点,问哪些点可以无限拓展,哪些点不能。

可以无限拓展的点只需要在上下左右任何一个方向可以无限拓展,不能无限拓展的点在四个方向都不能无限拓展。

考虑每个点和一个方向如向上

当这个点不能沿着这个方向拓展时,有两种情况

第一种情况是另一个点在这个点的正上方,如图(蓝色点为讨论的点,红色点为阻拦的点,黑色为分界线)

pk8x8u8.md.png

第二种情况下,先讨论两个不在一条竖直直线上时,形成的图形,如图
pk8x1jf.md.png

在有两个点阻拦的情况下,有如下两种情况(绿色点为另一个阻拦的点)

pk8xlgP.md.png

pk8xGDS.md.png

所以在第二种情况中,右边与左上方有点,左边与右上方有点,左上方与右上方有点的三种方法都可以阻拦向上无限拓展。

所以对每个点分别维护它的上,下,左,右,左上,左下,右上,右下的八个方向是否分别有点,并结合八个方向上是否有点,得出该点是否可以无限拓展。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
const int N=1000005;
int n,tx[N],nx,ty[N],ny,tr[N];
bool u[N],d[N],l[N],r[N],lu[N],ld[N],ru[N],rd[N],res[N],ans[N];
struct Point{
    int x,y,id;
    Point(){}
    Point(int _x,int _y){x=_x,y=_y;}
}a[N];
inline bool cmp(const Point&a,const Point&b){return a.x^b.x?a.x<b.x:a.y<b.y;}
inline void add(int p,int x){for(;p<=ny;p+=p&-p)tr[p]+=x;}
inline int que(int p){
    int res=0;
    for(;p;p-=p&-p)res+=tr[p];
    return res;
}
inline int sum(int l,int r){return que(r)-que(l-1);}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",tx+i,ty+i),a[i]=Point(tx[i],ty[i]);
    std::sort(tx+1,tx+n+1),nx=std::unique(tx+1,tx+n+1)-tx-1,std::sort(ty+1,ty+n+1),ny=std::unique(ty+1,ty+n+1)-ty-1;
    for(int i=1;i<=n;i++)a[i]=Point(std::lower_bound(tx+1,tx+nx+1,a[i].x)-tx,std::lower_bound(ty+1,ty+ny+1,a[i].y)-ty),a[i].id=i;
    std::sort(a+1,a+n+1,cmp);
    for(int i=1,j;i<=n;i=j+1){
        for(j=i;a[j+1].x==a[i].x;j++);
        for(int k=i;k<=j;k++){
            if(sum(1,a[k].y-1))ld[k]=true;
            if(sum(a[k].y+1,ny))lu[k]=true;
            if(sum(a[k].y,a[k].y))l[k]=true;
        }
        for(int k=i;k<=j;k++)add(a[k].y,1);
    }
    memset(tr,0,sizeof(tr));
    for(int i=n,j;i;i=j-1){
        for(j=i;a[j-1].x==a[i].x;j--);
        for(int k=j;k<=i;k++){
            if(sum(1,a[k].y-1))rd[k]=true;
            if(sum(a[k].y+1,ny))ru[k]=true;
            if(sum(a[k].y,a[k].y))r[k]=true;
        }
        for(int k=j;k<=i;k++)add(a[k].y,1);
    }
    memset(tr,0,sizeof(tr));
    for(int i=1,j;i<=n;i=j+1){
        for(j=i;a[j+1].x==a[i].x;j++);
        for(int k=i;k<=j;k++)add(a[k].y,1);
        for(int k=i;k<=j;k++){
            if(sum(1,a[k].y-1))d[k]=true;
            if(sum(a[k].y+1,ny))u[k]=true;
        }
        for(int k=i;k<=j;k++)add(a[k].y,-1);
    }
    for(int i=1;i<=n;i++){
        if(lu[i]&&ru[i]||lu[i]&&r[i]||ru[i]&&l[i])u[i]=true;
        if(lu[i]&&ld[i]||lu[i]&&d[i]||ld[i]&&u[i])l[i]=true;
        if(ru[i]&&rd[i]||ru[i]&&d[i]||rd[i]&&u[i])r[i]=true;
        if(ld[i]&&rd[i]||ld[i]&&r[i]||rd[i]&&l[i])d[i]=true;
        if(l[i]&&u[i]&&r[i]&&d[i])res[i]=true;
    }
    for(int i=1;i<=n;i++)ans[a[i].id]=res[i];
    for(int i=1;i<=n;i++)putchar(ans[i]?'0':'1');
    return puts(""),0;
}

最后,还是儿童节快乐捏。

标签:GDKOI2024,普及,minn,int,儿童节,tr,拓展,fa,include
From: https://www.cnblogs.com/junjunccc/p/18226037

相关文章

  • 打卡信奥刷题(35)用Scratch图形化工具信奥P1664 [ 普及组] 每日打卡心情好
    每日打卡心情好题目背景在洛谷中,打卡不只是一个简单的鼠标点击动作,通过每天在洛谷打卡,可以清晰地记录下自己在洛谷学习的足迹。通过每天打卡,来不断地暗示自己:我又在洛谷学习了一天,进而帮助自己培养恒心、耐心、细心。此外,通过打卡,还可以获取经验值奖励,经验值的多少在一定......
  • 低代码与大模型时代:技术的进化与人工智能的普及
    在当前快速发展的技术环境中,低代码和大模型成为了推动技术创新和人工智能普及的关键因素。低代码开发平台使得软件开发变得更简单和高效,大模型则提供了更强大的智能能力。这篇文章将探讨低代码和大模型在技术领域的应用,以及它们对于普通用户和开发者的影响。低代码开发平台的......
  • CSP历年复赛题-P1980 [NOIP2013 普及组] 计数问题
    原题链接:https://www.luogu.com.cn/record/160821231题意解读:统计1~n中x的个数。解题思路:枚举每个数,提取每一位,判断是否等于x。100分代码:#include<bits/stdc++.h>usingnamespacestd;intn,x,ans;intmain(){cin>>n>>x;for(inti=1;i<=n;i++)......
  • CSP历年复赛题-P1078 [NOIP2012 普及组] 文化之旅
    原题链接:https://www.luogu.com.cn/problem/P1078题意解读:1~n个国家,每个国家有自己的文化,不同国家文化可以相同,要从起点遍历到终点,已经学习过的文化不能重复学习,已经学习过的文化被某个文化歧视的国家也不能遍历,且不同国家之间有边,边有不同的距离,计算从起点到终点的最短路径。解......
  • 打卡信奥刷题(32)用Scratch图形化工具信奥P1055 [NOIP2008 普及组] ISBN 号码
    [NOIP2008普及组]ISBN号码题目描述每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括999位数字、1......
  • 儿童节变身小小音乐家,用ModelArts制作一张AIGC音乐专辑
    本文分享自华为云社区《儿童节变身小小音乐家,用ModelArts制作一张AIGC音乐专辑》,作者:华为云社区精选。儿童节,如何给小朋友准备一份特别的礼物?这份AIGC音乐专辑制作攻略一定要收下一段文字灵感就能编织出一曲悠扬悦耳的旋律童话、梦幻、探险……任何关键词都可以成为音乐的......
  • CSP历年复赛题-P1075 [NOIP2012 普及组] 质因数分解
    原题链接:https://www.luogu.com.cn/problem/P1075题意解读:求n的两个素因子中较大的一个。解题思路:数论的简单题,关键在于要知道一定有一个素因子不超过sqrt(n),而另一个素因子必然大于或等于sqrt(n),这样才能减少枚举时间。100分代码:#include<bits/stdc++.h>usingnamespaces......
  • CSP历年复赛题-P1310 [NOIP2011 普及组] 表达式的值
    原题链接:https://www.luogu.com.cn/problem/P1310题意解读:+代表按位或运算,*代表按位与运算,给定一个没有填数字的表达式,要求结果为0的数字方案数。解题思路:下面一步一步,由浅入深的来解决本题思路一(20分做法):观察得知,20%的数据,只有10个符号,且没有括号,也就是对应数字最多11个,可以......
  • 【NOIP2017普及组复赛】题2:图书管理员
    题2:图书管理员【题目描述】图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个正整数。每位借书的读者手中有一个需求码,这个需求码也是一个正整数。如果一本书的图书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的。小......
  • #[NOIP2003 普及组] 乒乓球
    传送锚点:https://www.luogu.com.cn/problem/P1042题目背景国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中\(11\)分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓......