首页 > 其他分享 >CF 2002 D1. DFS Checker (Easy Version) (*1900)思维

CF 2002 D1. DFS Checker (Easy Version) (*1900)思维

时间:2024-09-02 13:52:05浏览次数:3  
标签:cand int auto CF DFS son 2002 fa define

CF 2002 D1. DFS Checker (Easy Version) (*1900)思维

题目链接

题意

给你一棵 \(n\) 个节点组成的完全二叉树,并给出一个排列 \(p\) 。接下来进行 \(q\) 次询问。

每次询问给你 \(x\) 和 \(y\) ,你需要交换 \(p_x\) 和 \(p_y\)。并且回答交换之后的排列 \(p\) 是否是这棵

完全二叉树的DFS序。交换是持久的。

思路

我们可以将每个节点在DFS序中的位置看做点权。那么我们发现对于每棵子树中的节点,它的点权一定是连续的。

由于是排列,不会重复,因此我们只需要比较最小值和最大值即可。这样每次判断每个节点即可。我们可以对每个节点维护其儿子的集合。

对于修改:我们直接暴力维护好set即可。

时间复杂度 \(O(nlog^2n)\)

代码

#include<bits/stdc++.h>

using namespace std;

#define ff first
#define ss second
#define pb push_back
#define all(u) u.begin(), u.end()
#define endl '\n'
#define debug(x) cout<<#x<<":"<<x<<endl;

typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10, M = 105;
const int mod = 1e9 + 7;
const int cases = 1;

void Showball(){
   int n,q;
   cin>>n>>q;
   vector<int> e[n+1],fa(n+1),p(n+1),a(n+1);
   set<int> son[n+1];
   for(int i=1;i<=n;i++) e[i].clear(),son[i].clear();
   for(int i=2;i<=n;i++){
     cin>>fa[i];
     e[fa[i]].pb(i);
   }
   for(int i=1;i<=n;i++){
     cin>>p[i];
     a[p[i]]=i;
   }

   vector<int> sz(n+1);
   int cnt=0;

   auto check=[&](int u){
     return a[u]==*son[u].begin()&&a[u]+sz[u]-1==*son[u].rbegin();
   };

   function<void(int,int)> dfs=[&](int u,int father){
      sz[u]=1;son[u].insert(a[u]);
      for(auto v:e[u]){
        if(v==father) continue;
        dfs(v,u);
        sz[u]+=sz[v];
        for(auto it:son[v]) son[u].insert(it); 
      }
      cnt+=check(u);
   };

   dfs(1,0);
   while(q--){
    int x,y;
    cin>>x>>y;
    swap(p[x],p[y]);
    x=p[x],y=p[y];
    vector<int> cand;
    for(int i=x;i;i=fa[i]) cand.pb(i);
    for(int i=y;i;i=fa[i]) cand.pb(i);
    sort(all(cand));
    cand.erase(unique(all(cand)),cand.end());
    for(auto it:cand) cnt-=check(it);
    for(int i=x;i;i=fa[i]) son[i].erase(a[x]);
    for(int i=y;i;i=fa[i]) son[i].erase(a[y]);
    swap(a[x],a[y]);
    for(int i=x;i;i=fa[i]) son[i].insert(a[x]);
    for(int i=y;i;i=fa[i]) son[i].insert(a[y]);
    for(auto it:cand) cnt+=check(it);
    cout<<(cnt==n?"Yes\n":"No\n");
   }

}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    if(cases) cin>>T;
    while(T--)
    Showball();
    return 0;
}

标签:cand,int,auto,CF,DFS,son,2002,fa,define
From: https://www.cnblogs.com/showball/p/18392577

相关文章

  • CF 2004 D. Colored Portals (*1600) 二分
    CF2004D.ColoredPortals(*1600)二分题目链接题意:有\(n\)座城市,编号从\(1\)到\(n\)。传送门一共有\(4\)种颜色,每个城市有两种不同颜色的传送门。若城市\(i\)和城市\(j\)有相同颜色的传送门。那么就可以花费\(|i-j|\)枚金币从城市\(i\)到城市\(j\)。\(q\)......
  • CF2008场题解
    Sakurako'sExam算法:模拟,分类讨论。题意简述:给\(a\)个数字\(1\)和\(b\)个数字\(2\),问能否在每个数字前加上加减号使得原始值为\(0\)。考虑\(1\)的个数如果是奇数,那么一定不行。否则如果\(2\)的个数是偶数,一定可以。当\(2\)的个数为奇数且还可能可以时,判断是否存......
  • CF 有趣题目做题笔记
    CF1157FMaximum_Balanced_CircleProblem题意:给出一个长度为\(n\)的序列\(a\),你可以选出序列的任意子集。记这个子集为\(b\),大小为\(k\),则需要满足\(\lvertb_i-b_{(i+1)\bmodk}\rvert\le1\)。你需要最大化\(k\)的值,并输出选出的子集\(b\)。Solution注意到最终......
  • CF1826D
    CF1826D链接:Problem-1826D-Codeforces题目大意:给你一个数组,让你选择一个区间\([l,r]\)设选中的区间为\(b\),\(b_{i_1}+b_{i_2}+b_{i_3}\)为区间内前三大的值,你需要选择一个区间使得\(b_{i_1}+b_{i_2}+b_{i_3}-(r-l)\)值最大,输出最大值思路:我们发现......
  • CF2003
    CF2003A考虑特殊情况,划分为\(2\)个串,判定\(s_1\nes_n\)即可B具有单调性,二分判定或者考虑贪心,考察\(\min\),先手必然要删,且随时能删,删了会让后面条件更容易满足,所以第一个删,归纳即可trick:枚举判定$\rightarrow$二分C贪心,每次选择最大和次大填即可D1&D2D1是\(......
  • CF2006
    CF2006A发现\(01\)和\(10\)相差不超过\(1\),就是关注\(01\)段个数,中间插入\(01\)不影响段的奇偶性,转化为路径首尾不同一种较优策略是先手固定根,其实还可以让后手固定根,当\(c_0=c_1\)答案可能会大\(1\),分讨即可B显然一条边只属于两条路径,暴力维护即可C考虑证明当......
  • CCF-CSP 2024 --重塑矩阵1,2c语言题解
     创作想法是因为像我当初大一时候想参加一些比赛但是奈何只学了c和c相关数据结构,但是对于许多竞赛的题目的题解往往都是c++或者其他面向对象的编程语言,让我们难以在c语言基础上入手这些比较复杂的题目。 创造的目的是为了帮助各位同时提高我对c语言编程的理解和锻炼个人......
  • CF1741F-Multi-ColoredSegments
    https://www.luogu.com.cn/problem/CF1741Fhttps://codeforces.com/contest/1741/problem/F参考:https://www.luogu.com.cn/article/bb54tb8m考虑用线段树维护每个点被几条线段覆盖,然后按照颜色分类,每次做其中一类,把同类颜色从线段树中去掉,然后先区间求和看有没有重叠,再左端点往......
  • 题解:CF916D Jamie and To-do List
    题意维护一个数据结构,支持以下几种操作:setaixi:设置任务\(a_i\)的优先级为\(x_i\),如果该列表中没有出现则加入该任务。removea_i:删除该任务。querya_i:求优先级比\(a_i\)小的任务个数,如果没有则输出\(-1\)。undosum:删除此次操作之前的\(sum\)次操作。分析前......
  • 题解:CF916B Jamie and Binary Sequence (changed after round)
    题意把一个数分解成恰好\(k\)个\(2^{a_i}\)次方的和,可以重复,要求保证最大的\(a_i\)要尽可能的小时,\(a\)的字典序尽可能大,输出序列\(a\)。分析首先我们借助二进制拆出一个满足\(n=\sum2^{a_i}\)序列\(a\),满足\(a\)的长度最小。若此时\(a\)的长度大于\(k\),显......