首页 > 其他分享 >暑假集训CSP提高模拟26

暑假集训CSP提高模拟26

时间:2024-08-21 17:37:58浏览次数:8  
标签:26 dist int long 集训 FILE using CSP 节点

赛时rank17,T1 18,T2 50,T3 0,T4 40

博弈

异或hash。

当crying必胜时,一定为有一个权值出现次数为奇数,证明是显然的。

然后就可以考虑异或了。

将每个相同的权值换成一个很大的随机权值,然后在树上异或。两个点之间的路径为\(dist_x\oplus dist_y \oplus dist_{lca} \oplus dist_{lca} = dist_x \oplus dist_y\)

不合法的时候当且仅当\(dist_x\oplus dist_y=0\),将不合法的记录下来即可。

建议将权值换成大一点的,减少错误概率。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#ifdef LOCAL
    FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
    // FILE *ErrFile=errfile("err.err");
#else
    FILE *Infile = stdin,*OutFile = stdout;
    //FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 5e5 + 10;
struct EDGE{int to,next;ll w;}edge[N<<1];
int head[N],cnt;
inline void add(int u,int v,ll w){
    edge[++cnt] = {v,head[u],w};
    head[u] = cnt;
}
int n,u[N],v[N];
ll w[N];
ll dist[N],rd[N];
unordered_map<ll,int> mp;
void dfs(int x,int fa){
    mp[dist[x]]++;
    for(int i = head[x]; i;i = edge[i].next){
        int y = edge[i].to;
        if(y == fa) continue;
        dist[y] = dist[x]^edge[i].w;
        dfs(y,x);
    }
}
inline void solve(){
mt19937_64 rnd((ull)(new char));
int T;cin>>T;
while(T--){
    cin>>n;
    vector<int> num;
    for(int i = 1;i < n; ++i) cin>>u[i]>>v[i]>>w[i],num.emplace_back(w[i]);
    cnt = 0;
    for(int i = 1;i <= n; ++i) head[i] = 0;
    unordered_map<ll,int> ().swap(mp);
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    for(int i = 1;i <= n; ++i) rd[i] = rnd();
    for(int i = 1;i < n; ++i) 
        w[i] = lower_bound(num.begin(),num.end(),w[i]) - num.begin() + 1;
    for(int i = 1;i < n; ++i) w[i] = rd[w[i]];
    for(int i = 1;i < n; ++i) add(u[i],v[i],w[i]),add(v[i],u[i],w[i]);
    dfs(1,0);
    ll ans = 0;
    for(auto i:mp) ans += 1ll*i.second*(i.second-1);
    cout<<(1ll*n*(n-1)-ans)/2<<'\n';
}
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    solve();
}

跳跃

一个没有看懂的dp

image

大陆

[SCOI2005] 王室联邦

神奇的构造题,神(晶晶晶)说是树分块前置知识,膜拜神~~~~~~~~~

构造方法 :

  1. dfs整棵树,对于dfs到的一个节点,将其符合条件的子节点分块,将未被分块的返回上一层,这个用一个栈维护即可。

  2. 将未被分块的子节点添加到现集合\(S\)中,如果\(|S|\ge B\)那么就将该节点设为省会,然后清空\(S\)

  3. 处理完所有的子树后,再将当前节点加入\(S\)中,返回上一层。

  4. 如果dfs完后还有节点,那么以根节点为省会,并入一个块即可。

证明 :

考虑到对于每个节点,它上传回去的节点最多为\(B-1\),所以每次在枚举到的点的集合大小最大为\(B-1+1=B\)。

又由于返回的集合最大为\(B\),一个子树的贡献最多为\(B-1\),所以一个块最多为\(2\times B-1\),符合条件。

最后的剩余节点最多为\(B\),加上原来的节点最多为\(3\times b-1\),符合条件

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#ifdef LOCAL
    FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
    // FILE *ErrFile=errfile("err.err");
#else
    FILE *Infile = stdin,*OutFile = stdout;
    //FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 1e3 + 10;
struct EDGE{int to,next;}edge[N<<1];
int head[N],cnt;
inline void add(int u,int v){
    edge[++cnt] = {v,head[u]};
    head[u] = cnt;
}
int n,m,tot,rt[N],bel[N],sta[N],top;
void dfs(int x,int fa){
    int cur = top;
    for(int i = head[x]; i;i = edge[i].next){
        int y = edge[i].to;
        if(y == fa) continue;
        dfs(y,x);
        if(top - cur >= m){
            rt[++tot] = x;
            while(top > cur) bel[sta[top--]] = tot;
        }
    }
    sta[++top] = x;
}
inline void solve(){
    cin>>n>>m;
    for(int i = 1,u,v;i < n; ++i) cin>>u>>v,add(u,v),add(v,u);
    dfs(1,0);
    if(!tot) rt[++tot] = 1;
    while(top) bel[sta[top--]] = tot;
    cout<<tot<<'\n';
    for(int i = 1;i <= n; ++i) cout<<bel[i]<<' ';
    cout<<'\n';
    for(int i = 1;i <= tot; ++i) cout<<rt[i]<<' ';
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    solve();
}

排列

神奇的\(fhq\_treap\)题,不会。

image

标签:26,dist,int,long,集训,FILE,using,CSP,节点
From: https://www.cnblogs.com/hzoi-Cu/p/18372201

相关文章

  • CF1264D1 题解
    blog。写一个题解区没有的蠢做法,不依赖dp但是很难转到HardVersion(对于已经确定的序列,深度有单调性。就是如果答案为\(x\),那么肯定能选出深度为\(1\simx\)的子序列。记\(\operatorname{check}_s(x)\)表示check序列\(s\)能否选出深度为\(x\)的子序列。考虑如何c......
  • 电力系统潮流计算(牛顿-拉夫逊法、高斯-赛德尔法、快速解耦法)【6节点 9节点 14节点 26
      ......
  • 【CSP:202312-1】仓库规划(Java)
    题目链接202312-1仓库规划题目描述求解思路暴力求解:由于数据量较小,对每个仓库进行遍历求解即可。需要注意只有一个仓库的特殊情况。(n=1......
  • 【CSP:202312-2】因子化简(Java)
    题目链接202312-2因子化简题目描述求解思路哈希表:利用哈希表记录下每个因数出现的次数。从222开始遍历,找出......
  • 2024.8.20 总结(集训)
    上午比较轻松,上课基本听懂。下午比较破防,写题一道都没过(就写了洛谷上点分治板子\(1\),还没过)。晚上照着别人的代码把下午那道题A了。教训:学新东西先看别人的博客[或者题解](?)(可以去博客园找。或者也许也可以先看洛谷上模板题的题解。)感谢nkp传授这一点经验。感觉自己代码......
  • 『模拟赛』暑假集训CSP提高模拟25
    Rank学新东西,不算挂分(确信。A.可持久化线段树原板子[SP11470]TTM-Tothemoon主席树,不过区间修改。赛时想到标记永久化了,不过打pushdown的时候没新开点,于是-100pts。还挺简单的,建树和更改动态开点,按线段树来,加个lazy,其他的就是普通线段树的操作。板子#include......
  • 2024暑假集训测试29
    前言比赛链接。今上午在家打的,下午回的学校,话说啥时候改成\(7\)点开始了?T1是板子但是没打过标记永久化,想了一段时间想起树状数组维护区间求和操作于是用主席树实现了这个,赛时T1不给大样例所以调了挺长时间才放心;T2想了一会儿没想出来就先打T3了,T3想了一会儿胡了个......
  • hdu2604
    用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1); 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf,fmf,mff,fff,其中fff和fmf不满足题意所以我们不考虑,但是如果是 mmf的话那么前n-3可以找满足条件的......
  • CSP 模拟 25
    T1可持久化线段树做法一:注意到\(\sumk<n\),所以数据结构直接暴力回溯是对的,然后做完了。做法二:还是注意到那个,记一下修改过的节点,然后回溯直接改节点。做法三:主席树区间修改,一直想写,但是好像没啥用这个东西,tothemoon是板子,我想抽时间玩玩tothemoonT2LittleBusters!......
  • 暑假集训CSP提高模拟25
    赛时rank5,T1100,T285,T350,T45T2Tarjan意外挂了,在Tarjan里判割边会挂?T3\(O(nm^2)\)暴力能拿50?特判样例能拿60?可持久化线段树没啥好说的,主席树板子。点此查看代码#include<bits/stdc++.h>#include<bits/extc++.h>//usingnamespace__gnu_pbds;//usingnames......