[luogu3767]膜法

[luogu3767]膜法

luogu
神仙题
线段树分治+带权并查集
把每个操作看成点
首先这个操作的结构是一棵树
你发现每个点的对它的子树产生影响
我们可以想到用dfn序把它转成一段区间用线段树分治来做
但是还有删除操作,相当于在一个大区间里面挖掉几个小区间
可以对每个操作开一个vector记录区间搞一搞
然后带权并查集是模5意义下的,可以认为给你的操作相当于从u连向v的一条权值为1或2的边
当u,v在同一个集合时,判断是否满足条件,否则就连边

#define pb push_back
#define ls x<<1,l,mid
#define rs x<<1|1,mid+1,r
#include<bits/stdc++.h>
using namespace std;
const int _=1e5+5;
int re(){
    int x=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}
int n,m,ts,top,dis;
int fa[_],del[_],sz[_],dfn[_],par[_],siz[_],d[_];
bool ans[_];
struct node{int u,v;}st[_];
struct edge{int u,v,w;}e[_];
vector<int>son[_],s[_];
vector<edge>t[_<<2];
void dfs(int u){
    sz[u]=1;if(u)dfn[u]=++ts;
    if(del[u])s[del[u]].pb(u);
    for(int i=0,j=son[u].size();i<j;i++){
        int v=son[u][i];
        dfs(v);sz[u]+=sz[v];
    }
}
void add(int&x,int y){x=(x+y)%5;}
int find(int x){
    add(dis,d[x]);
    if(x==par[x])return x;
    return find(par[x]);
}
void upd(int x,int l,int r,int ql,int qr,edge E){
    if(ql<=l&&r<=qr){t[x].pb(E);return;}
    int mid=(l+r)>>1;if(ql<=mid)upd(ls,ql,qr,E);
    if(qr>mid)upd(rs,ql,qr,E);
}
void solve(int x,int l,int r,bool ok){
    int pre=top;
    for(int i=0,j=t[x].size();i<j;i++){
        int u=t[x][i].u,v=t[x][i].v,w=t[x][i].w;
        dis=0;int fu=find(u),du=dis;
        dis=0;int fv=find(v),dv=dis;
        if(fu==fv&&(du-dv+5)%5!=w)ok=0;
        if(fu^fv){
            if(siz[fu]>siz[fv]){swap(du,dv);swap(u,v);swap(fu,fv);w=-w;}
            siz[fv]+=siz[fu];par[fu]=fv;
            d[fu]=(w+dv-du+10)%5;st[++top]=(node){fu,fv};
        }
    }
    if(l==r)ans[l]=ok;
    else{int mid=(l+r)>>1;solve(ls,ok);solve(rs,ok);}
    while(top^pre){
        int u=st[top].u,v=st[top].v;top--;
        siz[v]-=siz[u];par[u]=u;d[u]=0;
    }
}
int main(){
    n=re(),m=re();
    int op,u,v;
    for(int i=1;i<=m;i++){
        son[fa[i]=re()].pb(i);op=re();
        if(op==3)del[i]=re();
        else{u=re(),v=re();e[i]=(edge){u,v,op};}
    }
    dfs(0);
    for(int i=1;i<=m;i++){
        if(del[i])continue;
        int k=s[i].size(),lst=dfn[i];
        for(int j=0;j<k;j++){
            int u=s[i][j];
            if(lst<dfn[u])upd(1,1,m,lst,dfn[u]-1,e[i]);
            lst=dfn[u]+sz[u];
        }
        if(lst<dfn[i]+sz[i])upd(1,1,m,lst,dfn[i]+sz[i]-1,e[i]);
    }
    for(int i=1;i<=n;i++)par[i]=i,siz[i]=1;
    solve(1,1,m,1);
    for(int i=1;i<=m;i++)puts(ans[dfn[i]]?"excited":"naive");
    return 0;
}

原文地址:https://www.cnblogs.com/sdzwyq/p/9879121.html

时间: 2024-10-11 22:47:46

[luogu3767]膜法的相关文章

奇怪的膜法(magic)——前缀和做法

题目描述 Zxyer是M国一个伟大的膜法师,现在他制作出了n个膜法球,每个膜法球有一个初始膜力值,由亍zxyer现在在修炼膜法,因此zxyer现在会对这些按照编号为1~n顺序依次排列的膜法球进行m次操作,每次zxyer会将一个区间的膜法球拿出,然后将他们的膜力值依次增加一个等差数列,现在zxyer想要知道在他施法全部结束后,这些膜法球各自的膜力值. 输入 第一行2个整数,n,m,定义参见问题描述. 第2行n个整数,ai,表示膜法球各自的初始膜力值. 第3~m+2行,每行3个整数,Li,Ri,qi

【OpenJudge3531】【背包DP】【膜法交配律】判断整除

判断整除 总时间限制: 1000ms 内存限制: 65536kB [描述] 一个给定的正整数序列,在每个数之前都插入+号或-号后计算它们的和.比如序列:1.2.4共有8种可能的序列:(+1) + (+2) + (+4) = 7(+1) + (+2) + (-4) = -1(+1) + (-2) + (+4) = 3(+1) + (-2) + (-4) = -5(-1) + (+2) + (+4) = 5(-1) + (+2) + (-4) = -3(-1) + (-2) + (+4) = 1(-

cogs1685 膜法森林 神奇的SPFA

继续填坑--链接:http://cogs.pro/cogs/problem/problem.php?pid=1685 题意:两种费用,求出两种费用最小的和. 正解是$LCT$--但是这里有一个令人惊掉下巴的做法-- 不断枚举每一条边所需的第一种费用,对于满足这一条件下的边加入图中,同时压入队列,随后跑最短路,跑出一次更新一次最小值-- 恩就这么做出来了-- 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring&g

memcached+varnish

memcached 缓存服务器: 1.缓存:cache,无持久存储功能 2.行挂失缓存bypass,而不是代理式缓存 3.仅提供缓存功能,存什么,怎么存全有客户端决定 4.k/v cache,只能存储可序列化数据 5.存储项是非常简单的:key,value,flag,expire time(过期时间)单数上限:1M 6.功能的实现一把依赖于memcached,一半是client 7.不能高可用,挂了缓存就丢失了 8.O(1)的执行效率 9.分布式缓存互不通信的分布式集群 分布式系统请求路由方法:

程序员超浓鸡汤,知乎上赞同数最高的999个回答

原文出处 http://lanbing510.info/2016/04/14/ZhiHu-Good-Answers.html#title0 最近发现这个文章,真的是非常适合程序员看的鸡汤文列表,超强浓缩版的!!! 1哪些素质很重要,却是读书学不来的?101501肥肥猫 2有哪些很重要又被忽视的炒菜技巧?85658庄力 3想要充实自己,有哪 10 本书和 10 部电影值得推荐?77738Jee Xin 4要怎样努力,才能成为很厉害的人?76144朱炫 5如何看待「医生拒绝给艾滋病人做手术」?748

(最短路)17bupt新生赛——F. ch追妹

F. ch追妹 2017新生赛 时间限制 2000 ms 内存限制 65536 KB 题目描述 n个点的一张无向图,每条边长度为wi,ch站在a点,ch要追的妹子站在b点.ch可以使用一次膜法,将一条边的长度变为0.ch想知道他要追到妹子要走的最短路径. 输入格式 第一行为数据组数T(T≤10).每组数据的第一行为四个数 n,m,a,b(1≤a,b≤n≤10000,1≤m≤50000),分别表示点数,边数,ch的位置,妹子的位置.之后m行,每行为三个数 u,v,w(1≤u,v≤n;1≤w≤100

[日常训练]变戏法

Description 一开始有$n$个只有颜色不同的小球.定义使用一次膜法的效果是重新排列第$l_i$个到第$r_i$个小球.给定了$n$个小球的初始状态和最终状态,以及$m$次膜法的范围$l_i,r_i$.判断是否可以从初始状态转移到最终状态. Input 第一行有一个整数$t$表示数据组数. 每组数据中, 第一行两个整数$n,m$,表示总共有$n$个小球,$m$次操作. 第二行$n$个整数$a_i$,表示初始状态. 第三行$n$个整数$b_i$,表示最终状态. 接下来$m$行,每行两个整数

CSU 1948: 超级管理员(费用流)

Description 长者对小明施加了膜法,使得小明每天起床就像马丁的早晨一样. 今天小明早上醒来发现自己成了一位仓管员.仓库可以被描述为一个n?×?m的网格,在每个网格上有几个箱子(可能没有).为了防止倾倒,每个网格上,箱子不应该堆放超过h个.为了满足要求,小明需要搬一些箱子,每一次,他可以把箱子从一个网格到相邻的网格(如果两个网格共享一条边). 请计算为了满足要求,小明至少需要搬多少次. Input 第一行一个整数T,表示有T组测试数据. 接下来每组数据,第一行有3个整数n,?m,?h(1

河南工业大学2017校赛题解

问题 A: 饶学妹的比赛 题意: 给你一场比赛每人提交的记录,计算最后的排名 题解: 模拟+排序 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #