首页 > 其他分享 >冲刺国赛模拟 5

冲刺国赛模拟 5

时间:2023-05-17 17:02:18浏览次数:49  
标签:get int tree 冲刺 edge 国赛 id 模拟 dis

今天上午给我整不会了,开着空调结果冻的要死,这还是外边三十多度的情况下。结果一上午两眼发黑打题,心态相当爆炸。

题目名称好像是 qlr 洛谷主页。

今晚九点

简单题。为啥赛时没人做。

在每个位置有意义的走法显然只有两种:用 \(2\) 步走到相邻一格,或者用 \(1\) 步走到头。那每个点最多 \(8\) 条边连出去,直接跑最短路就行。

int n,m,num,id[1010][1010];
char s[1010][1010];
struct node{
    int v,w,next;
}edge[8000010];
int t,head[1000010];
void add(int u,int v,int w){
    edge[++t].v=v;edge[t].w=w;edge[t].next=head[u];head[u]=t;
}
struct stu{
    int x,w;
    bool operator<(const stu&s)const{
        return w>s.w;
    }
};
priority_queue<stu>q;
int dis[1000010];
bool vis[1000010];
void dijkstra(int st){
    memset(dis,0x3f,sizeof(dis));
    dis[st]=0;q.push({st,0});
    while(!q.empty()){
        int x=q.top().x;q.pop();
        if(!vis[x]){
            vis[x]=true;
            for(int i=head[x];i;i=edge[i].next){
                if(dis[edge[i].v]>dis[x]+edge[i].w){
                    dis[edge[i].v]=dis[x]+edge[i].w;
                    if(!vis[edge[i].v])q.push({edge[i].v,dis[edge[i].v]});
                }
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
        for(int j=1;j<=m;j++)id[i][j]=++num;
    }
    for(int i=2;i<n;i++){
        int pre;
        for(int j=2;j<m;j++){
            if(s[i][j]=='#')continue;
            if(s[i][j]=='.'&&s[i][j-1]=='#')pre=j;
            if(j^pre)add(id[i][j],id[i][pre],1);
            if(s[i][j]=='.'&&s[i][j-1]=='.')add(id[i][j],id[i][j-1],2);
        }
        for(int j=m-1;j>=2;j--){
            if(s[i][j]=='#')continue;
            if(s[i][j]=='.'&&s[i][j+1]=='#')pre=j;
            if(j^pre)add(id[i][j],id[i][pre],1);
            if(s[i][j]=='.'&&s[i][j+1]=='.')add(id[i][j],id[i][j+1],2);
        }
    }
    for(int j=2;j<m;j++){
        int pre;
        for(int i=2;i<n;i++){
            if(s[i][j]=='#')continue;
            if(s[i][j]=='.'&&s[i-1][j]=='#')pre=i;
            if(i^pre)add(id[i][j],id[pre][j],1);
            if(s[i][j]=='.'&&s[i-1][j]=='.')add(id[i][j],id[i-1][j],2);
        }
        for(int i=n-1;i>=2;i--){
            if(s[i][j]=='#')continue;
            if(s[i][j]=='.'&&s[i+1][j]=='#')pre=i;
            if(i^pre)add(id[i][j],id[pre][j],1);
            if(s[i][j]=='.'&&s[i+1][j]=='.')add(id[i][j],id[i+1][j],2);
        }
    }
    int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    dijkstra(id[x1][y1]);
    if(dis[id[x2][y2]]==0x3f3f3f3f)dis[id[x2][y2]]=-1;
    printf("%d\n",dis[id[x2][y2]]);
    return 0;
}

小王唱歌

赛时冻的神志不清导致完美错过正解。

首先简单容斥一下,枚举边集。然后就变成了算每个连通块最小值的积。设 \(dp_{x,i}\) 为 \(x\) 子树,\(x\) 所在连通块最小值为 \(i\) 的答案,再设个 \(g\) 为不算 \(x\) 连通块的答案。转移很简单,考虑加不加入连通块:

\[g_{x,i}=g_{x,i}\sum dp_{v,j}-g_{x,i}\sum_{j>i}g_{v,j}-g_{v,i}\sum_{j>i}g_{x,j}-g_{x,i}g_{v,i} \]

只有后缀和,冲一发线段树合并就行了。

因为 pushup 没取模调了一个小时,警钟长鸣。

const int mod=998244353;
int n,cnt,b[500010],lsh[500010];
struct gra{
    int v,next;
}edge[1000010];
int tot,head[500010];
void add(int u,int v){
    edge[++tot].v=v;edge[tot].next=head[u];head[u]=tot;
}
struct node{
    #define lson tree[rt].ls
    #define rson tree[rt].rs
    int ls,rs,f,g,lz;
}tree[500010<<5];
int t,rt[500010];
void pushup(int rt){
    tree[rt].f=(tree[lson].f+tree[rson].f)%mod;
    tree[rt].g=(tree[lson].g+tree[rson].g)%mod;
}
void pushtag(int rt,int val){
    tree[rt].f=1ll*tree[rt].f*val%mod;
    tree[rt].g=1ll*tree[rt].g*val%mod;
    tree[rt].lz=1ll*tree[rt].lz*val%mod;
}
void pushdown(int rt){
    if(tree[rt].lz!=1){
        if(lson)pushtag(lson,tree[rt].lz);
        if(rson)pushtag(rson,tree[rt].lz);
        tree[rt].lz=1;
    }
}
void update(int &rt,int L,int R,int pos){
    if(!rt)rt=++t,tree[rt].lz=1;
    if(L==R){
        tree[rt].g=1;tree[rt].f=lsh[L];return;
    }
    int mid=(L+R)>>1;
    if(pos<=mid)update(lson,L,mid,pos);
    else update(rson,mid+1,R,pos);
    pushup(rt);
}
int merge(int x,int y,int l,int r,int sumx,int sumy,int val){
    if(!x&&!y)return 0;
    if(!x){
        pushtag(y,(mod-sumx)%mod);
        return y;
    }
    if(!y){
        pushtag(x,(val-sumy+mod)%mod);
        return x;
    }
    if(l==r){
        int ret=tree[x].g;
        tree[x].g=1ll*tree[x].g*val%mod;
        tree[x].g=(tree[x].g-1ll*ret*sumy%mod+mod)%mod;
        tree[x].g=(tree[x].g-1ll*tree[y].g*sumx%mod+mod)%mod;
        tree[x].g=(tree[x].g-1ll*ret*tree[y].g%mod+mod)%mod;
        tree[x].f=1ll*tree[x].g*lsh[l]%mod;
        return x;
    }
    pushdown(x);pushdown(y);
    int mid=(l+r)>>1;
    tree[x].ls=merge(tree[x].ls,tree[y].ls,l,mid,(sumx+tree[tree[x].rs].g)%mod,(sumy+tree[tree[y].rs].g)%mod,val);
    tree[x].rs=merge(tree[x].rs,tree[y].rs,mid+1,r,sumx,sumy,val);
    pushup(x);
    return x;
}
void dfs(int x,int f){
    update(rt[x],1,cnt,b[x]);
    for(int i=head[x];i;i=edge[i].next){
        if(edge[i].v!=f){
            dfs(edge[i].v,x);
            rt[x]=merge(rt[x],rt[edge[i].v],1,cnt,0,0,tree[rt[edge[i].v]].f);
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]),lsh[i]=b[i];
    sort(lsh+1,lsh+n+1);
    cnt=unique(lsh+1,lsh+n+1)-lsh-1;
    for(int i=1;i<=n;i++)b[i]=lower_bound(lsh+1,lsh+cnt+1,b[i])-lsh;
    for(int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    dfs(1,0);
    printf("%d\n",tree[rt[1]].f);
    return 0;
}

不见不散

超级结论题。

首先如果操作数和逆序对数奇偶性不同显然无解。剩下的猜一下有解,开始构造。

设当前每个人有的礼物的排列为 \(p\),首先我们有显然的方法去掉一个 \(p_i\neq a_i\) 的数:把它和别的都交换一遍,并把 \(p_j=a_i\) 的 \(j\) 放到最后交换。这样去掉所有 \(p_i\neq a_i\) 的数,剩下的数都是 \(p_i=a_i\)。

考虑所有剩下的数,此时逆序对数为 \(0\),因此剩下的数个数一定满足 \(\bmod 4\equiv 0/1\)。那么四个四个去掉就行。

首先我们有方法用完两个数的操作次数并交换它们:设它们为 \(a,b\),先使 \(a\) 和除了 \(b\) 以外的所有数交换,然后交换 \(a,b\),最后把 \(b\) 按照 \(a\) 的操作顺序反过来操作。这样只有这两个数交换了,别的数都没有变化。那么四个数互相交换的方法是容易手模得到的,四个四个去掉就行了。

int n,cnt,p[1010],a[1010];
vector<int>S;
void get(int x,int y){
    if(x>y)swap(x,y);
    swap(p[x],p[y]);printf("%d %d\n",x,y);
}
void del(int x){
    for(vector<int>::iterator it=S.begin();it!=S.end();++it){
        if(*it==x){
            S.erase(it);break;
        }
    }
    int pos;
    for(int i:S)if(p[i]==a[x]){
        pos=i;break;
    }
    for(int i:S)if(pos!=i)get(x,i);
    get(x,pos);
}
void solve(int x,int y){
    for(int i:S)get(x,i);
    get(x,y);
    reverse(S.begin(),S.end());
    for(int i:S)get(y,i);
}
void calc(){
    int a=S.back();S.pop_back();
    int b=S.back();S.pop_back();
    int c=S.back();S.pop_back();
    int d=S.back();S.pop_back();
    solve(a,b);solve(c,d);
    get(a,c);get(b,d);get(a,d);get(b,c);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),p[i]=i,S.push_back(i);
    int cnt=0;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(a[i]>a[j])cnt++;
        }
    }
    if((cnt^(n*(n-1)>>1))&1){
        puts("NO");return 0;
    }
    puts("YES");
    while(1){
        bool jud=true;
        for(int i:S){
            if(p[i]!=a[i]){del(i);jud=false;break;}
        }
        if(jud)break;
    }
    while(S.size()>1)calc();
    return 0;
}

标签:get,int,tree,冲刺,edge,国赛,id,模拟,dis
From: https://www.cnblogs.com/gtm1514/p/17409297.html

相关文章

  • 第二次冲刺2
    刘嘉城:昨天我对换班操作进行了分析,确定了换班的逻辑思路今天我继续进行了换班的操作,我目前完成了两个员工之间的换班操作,利用sql语句来进行交换遇到的问题:没有调试好sql语句来交换两行的数据,会出现员工交换不了的情况 黄敏仪:昨天我对排班功能中的按照员工喜好和门店规则排班......
  • R语言布朗运动模拟股市、物种进化树状图、二项分布可视化
    全文链接:http://tecdat.cn/?p=32393原文出处:拓端数据部落公众号本文模拟了在连续和离散时间布朗演化一些简单的方法。布朗运动的数学模型(也称为随机游动)也可以用来描述许多现象以及微小颗粒的随机运动,如股市的波动和在化石中的物理特性的演变。布朗运动是随机模式,即改变了从一......
  • 模拟实现Promise
     Code:varMiniPromise=(functionMiniPromiseWrapper(){constPENDING='pending';constFULFILLED='fulfilled';constREJECTED='rejected';const_state=Symbol('state');const_result=Symbol(�......
  • 第二次冲刺1
    今天我们团队开始了第二次冲刺,下面是我们小组成员的工作情况田铭庚:今天我对Androidstudio连接mysql数据库实现web界面与Android手机端的信息传递做了一些工作           我通过在网络查询,得知Android链接数据库需要5.xx以下版本的数据库,然后需要将打开数......
  • 软件工程日报——第二次冲刺1
    今天我开始进行换班的操作,我的思路大概是在排班管理的界面上设置一个超链接,点击员工姓名跳转到一个换班的界面,选择一个员工进行换班,通过sql语句来实现员工的换班,请假功能与之类似,点击请假之后选择要替班的员工,通过sql语句来进行员工的替班  ......
  • 实验四 电子琴模拟实验
    实验四电子琴模拟实验实验目的1、了解单片机系统发声原理2、进一步熟悉定时器编程方法实验说明1、利用定时器,可以发出不同频率的脉冲,不同频率的脉冲经喇叭驱动电路放大滤波后,就会发出不同的音调。2、定时器按设置的定时参数产生中断,这一次中断发出脉冲低电平,下一次反......
  • 故障树 蒙特卡洛模拟 可靠性分析 采用故障树蒙特卡洛仿真进
    故障树蒙特卡洛模拟可靠性分析采用故障树蒙特卡洛仿真进行可靠性分析,根据系统故障树得到最小割集,matlab蒙特卡洛模拟,结合函数估计可靠性,验证仿真正确性,最后预测可靠性ID:82380669446020932......
  • 模拟退火算法—旅行商问题(TSP)优化 Matlab代码可用于路径规划,物流配送,路径优化
    模拟退火算法—旅行商问题(TSP)优化Matlab代码可用于路径规划,物流配送,路径优化源码+注释数据可以修改多少个坐标都行帮忙改数据就是另外的价钱[旺柴]代码一经售出概不退换!望理解ID:835675752236542......
  • Matlab利用蒙特卡洛模拟,将电动汽车EV分为一充二充三充三种类型,仿真电动汽车负荷曲线。
    Matlab利用蒙特卡洛模拟,将电动汽车EV分为一充二充三充三种类型,仿真电动汽车负荷曲线。蒙特卡洛模拟次数、电动汽车参数等易于修改。YID:5220643491185262......
  • 光伏电池模型 Matlab/Simulink仿真模型(成品) 模拟了光伏电池的
    光伏电池模型Matlab/Simulink仿真模型(成品)模拟了光伏电池的输出特性,可以自行改变光照强度和温度得到多组U-P、U-I曲线。图中光照强度400,温度为25度,这两个参数均可调节ID:4920674967291485......