首页 > 其他分享 >P6157 有趣的游戏

P6157 有趣的游戏

时间:2024-12-06 12:22:42浏览次数:5  
标签:cnt 游戏 P6157 int son 次大值 有趣 val

P6157 有趣的游戏

题意简述:

给你一棵树,要求你维护一条连上任意两点 \(w_x\) \(mod\) \(w_y\) 的最大值,以及在去掉这两个点后的整棵树山任意两点\(w_{x'}\) \(mod\) \(w_{y'}\) 的最大值

Solution:

我们不难发现,在一些数中最大的 \(w_x\) \(mod\) \(w_y\) 其实就是严格次大值 mod 最大值,它的结果等于严格次大值

所以我们只需要建一颗线段树来维护区间前四大值$ w_{[0,3]}$,及其数量 $ cnt_{[0,3]}$ 。对前一种答案直接输出链上严格次大值,然后将链上最大值 \(w_0\) 与链上严格次大值 \(w_1\) 在线段树节点[1,n]上 cnt--,(如果存在的话),然后在临时更新后的[1,n]上查一个严格次大值 就好了

Code:

#include<bits/stdc++.h>
const int N=1e5+5;
using namespace std;
int n,m;
int w[N];
struct Tree{
    int l,r;
    int val[5],cnt[5];
};
struct Segment_Tree{
    #define ls x<<1
    #define rs x<<1|1
    Tree t[N<<2];
    void clear(Tree &T)
    {
        for(int i=0;i<4;i++){T.val[i]=T.cnt[i]=0;}
    }
    void pushup(Tree &T,Tree L,Tree R)
    {
        int i=0,j=0,k=0;
        while(k<4)
        {
            if(L.val[i]==R.val[j])
            {
                T.val[k]=L.val[i];
                T.cnt[k]=L.cnt[i]+R.cnt[j];
                i++,j++,k++;
            }
            if(L.val[i]>R.val[j]&&k<4)
            {
                T.val[k]=L.val[i];
                T.cnt[k]=L.cnt[i];
                i++,k++;
            }
            if(L.val[i]<R.val[j]&&k<4)
            {
                T.val[k]=R.val[j];
                T.cnt[k]=R.cnt[j];
                j++,k++;
            }
        }
    }
    void build(int x,int l,int r)
    {
        t[x].l=l,t[x].r=r;
        if(l==r){t[x].val[0]=w[l];t[x].cnt[0]=1;return ;}
        int mid=l+r>>1;
        build(ls,l,mid);build(rs,mid+1,r);
        pushup(t[x],t[ls],t[rs]);
    }
    void upd(int x,int pos,int k)
    {
        if(t[x].l==t[x].r){clear(t[x]);t[x].val[0]=k;t[x].cnt[0]=1;return ;}
        int mid=t[x].l+t[x].r>>1;
        if(pos<=mid)upd(ls,pos,k);
        if(mid<pos) upd(rs,pos,k);
        pushup(t[x],t[ls],t[rs]);
    }
    void query(int x,int L,int R,Tree &res)
    {
        if(L<=t[x].l&&t[x].r<=R)
        {
            pushup(res,res,t[x]);
            return ;
        }
        int mid=t[x].l+t[x].r>>1;
        if(L<=mid)query(ls,L,R,res);
        if(mid<R) query(rs,L,R,res);
    }
    #undef ls
    #undef rs
}T;
struct Graph{
    int head[N];
    struct Edge{
        int to,nxt;
    }e[N<<1];
    void add(int x,int y)
    {
        e[++head[0]]=Edge{y,head[x]};
        head[x]=head[0];
    }
    int fa[N],top[N],dep[N],dfn[N],rid[N],val[N];
    int son[N],siz[N];
    void dfs1(int x,int ff)
    {
        dep[x]=dep[ff]+1;fa[x]=ff;
        siz[x]=1;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa[x])continue;
            dfs1(y,x);
            siz[x]+=siz[y];
            son[x] = siz[y] > siz[son[x]] ? y : son[x];
        }
    }
    void dfs2(int x,int tp)
    {
        dfn[x]=++dfn[0];rid[dfn[0]]=x;
        top[x]=tp;
        w[dfn[0]]=val[x];
        if(!son[x])return ;
        dfs2(son[x],tp);
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa[x]||y==son[x])continue;
            dfs2(y,y);
        }
    }
    Tree chain_query(int x,int y)
    {
        Tree res={0,0,{0},{0}};
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            T.query(1,dfn[top[x]],dfn[x],res);
            x=fa[top[x]];
        }
        if(dep[x]<dep[y])swap(x,y);
        T.query(1,dfn[y],dfn[x],res);
        return res;
    }

}G;
void work()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        G.add(x,y);G.add(y,x);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&G.val[i]);
    }
    G.dfs1(1,0);
    G.dfs2(1,1);
    T.build(1,1,n);
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==0)
        {
            w[G.dfn[x]]+=y;
            T.upd(1,G.dfn[x],w[G.dfn[x]]);
        }
        if(opt==1)
        {
            Tree A=G.chain_query(x,y);
            Tree B={0,0,{0},{0}};
            T.query(1,1,n,B);
            if(!A.val[1]){printf("%d\n",-1);continue;}
            int ans_A=A.val[1],ans_B=0;
            for(int j=0;j<2;j++)for(int k=0;k<4;k++)if(A.val[j]==B.val[k])B.cnt[k]--;
            for(int k=0,tag=0;k<4;k++){if(tag&&B.cnt[k]>0){ans_B=B.val[k];break;}if(B.cnt[k]>0)tag=1;}
            printf("%d %d\n",ans_A,ans_B);
        }
    }
}
int main()
{
    //freopen("P6157.in","r",stdin);freopen("P6157.out","w",stdout);
    work();
    return 0;
}

标签:cnt,游戏,P6157,int,son,次大值,有趣,val
From: https://www.cnblogs.com/LG017/p/18590496

相关文章

  • 用Python开发一个经典贪吃蛇小游戏
    Python是开发小游戏的绝佳工具,借助第三方库,如pygame,我们可以快速开发一个经典的贪吃蛇游戏。本篇将介绍如何用Python实现一个完整的贪吃蛇小游戏。一、游戏设计1.1游戏规则玩家通过方向键控制贪吃蛇移动。贪吃蛇吃到食物后会变长,同时得分增加。如果贪吃蛇撞到自己......
  • 鼠标键盘游戏手柄的测试代码
    #include"QtWidgetsApplication2.h"#include<windows.h>#include<QDebug>#include<QVBoxLayout>QtWidgetsApplication2::QtWidgetsApplication2(QWidget*parent):QFrame(parent){ui.setupUi(this); //init();}QtWidget......
  • 打怪小游戏
    #include<iostream>usingnamespacestd;doubleshengmingli=2000;//定义主角初始生命力intgongjili=150;//定义主角初始攻击力intfangyuli=200;//定义主角初始防御力intmoney=20;//定义主角初始金钱数量boolguoguan;//定义是否通关判定voidwuqidian();//......
  • 【Unity 科幻角色资产包】SCI FI CHARACTERS MEGA PACK Vol 1 大量高质量的科幻风格角
    SCIFICHARACTERSMEGAPACKVol1是一款专为Unity开发者设计的角色资产包,提供了大量高质量的科幻风格角色模型、纹理、动画和预设,旨在帮助开发者快速构建具有未来感的游戏角色,特别适合科幻、未来城市、太空战斗等类型的游戏。该插件包含了多种不同的角色和配件,可以用于创......
  • leetcode2836 在传球游戏中最大化函数值
    n名玩家在玩传球游戏,编号为i的玩家固定会把球传给编号为r[i]的玩家,任选一名玩家开始传球,恰好传k次,得分为这k次传球内所有接触过球的玩家的编号之和,如果玩家多次触球,则累加多次。问从哪个玩家开始传,能获得最大总得分,求最大得分。1<=n<=1E5;0<=r[i]<n;1<=k<=1E10分析:与倍增法求l......
  • HTML静态网页成品作业(HTML+CSS)——游戏阴阳师介绍网页(4个页面)
    ......
  • P9142 [THUPC 2023 初赛] 欺诈游戏 题解
    P9142[THUPC2023初赛]欺诈游戏题面这个游戏名叫《走私游戏》。游戏规则大概是这样的:一名玩家扮演走私者,一名玩家扮演检察官。走私者可以将\(x\)日元(\(x\)为\([0,n]\)内的整数,由走私者决定)秘密放入箱子中,而检查官需要猜测箱子中的金额。假设检察官猜了\(y\)(\(y\)也必......
  • C语言项目实现--数字游戏
    数字游戏根据用户选择,完成以下功能解一元二次方程;判断指定年份是否是闰年;判断某一数字是否是水仙花数简单了解:一元二次方程:仅注意观察▲即可闰年:普通润年:能被4整除但不能被100整除的年份世纪润年:能被400整除的世纪年(即以00结尾的年份)eg.1900可以被4整除(475),但不......
  • Python实战-猜数字游戏
    欢迎加入这场充满挑战与乐趣的猜数字游戏!在这个游戏中,计算机已经随机选择了一个1到10之间的数字作为目标。你的任务就是通过有限的猜测次数,找出这个神秘的数字。每一次猜测,你都会得到宝贵的反馈:如果猜得大了,就调整你的数字往小一点的方向猜;如果猜得小了,就勇敢地尝试更大的......
  • 一个有趣的插件,让写代码变成打怪升级的游戏
    前言本来是要安装个statistic插件来统计代码行数的无意中发现了Code::Stats这个插件看了下介绍挺有意思的效果这是我用这个插件写了两天代码后的成果,现在升到2级了这是总览可以详细看到每种语言的经验值每天各个时段的活跃程度后面还有一些其他详细的统计关......