首页 > 其他分享 >暑假集训csp提高模拟7

暑假集训csp提高模拟7

时间:2024-07-25 17:40:52浏览次数:5  
标签:FILE int top long 集训 num 暑假 using csp

赛时 rank 42,T1 80,T2 13,T3 0,T4 20

在T4挂死了,赛时胡了一个挺没有前途的\(O(n\log_2^3n)\)的做法,结果赛后发现假了,没有时间打T2,T3的暴力了。

T1 Permutations & Primes

Permutations & Primes

赛时有一个特判\(n=3\)错了,挂了20pts

结论非常显然,1放中间,2、3各放一边,剩下的随便放。

点此查看代码
#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)
using ll=long long;using ull=unsigned long long;using db = double;
#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
const int N = 2e5 + 10;
int n,a[N],ans[N];
vector<int> prime;
bitset<N> vis;
inline void Prime(int n){
	for(int i = 2;i <= n; ++i){
		if(!vis[i]) prime.push_back(i);
		for(auto j : prime){
			if(i*j > n) break;
			if(i % j == 0)break;
			vis[i*j] = true;
		}
	}
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
	Prime(N-10);
	int T;
	cin>>T;
	while(T--){
		cin>>n;
		if(n == 1){cout<<1<<'\n';continue;}
		if(n == 2){cout<<"1 2\n";continue;}
		if(n == 3){cout<<"2 1 3\n";continue;}
		int tot = 1,l = 1,r = n;
		vis.reset();
		for(auto i:prime){
			if(i > n) break;
			vis[i] = true;
			if(tot & 1) a[l++] = i,tot++;
			else a[r--] = i,tot++;
		}
		a[n/2+1] = 1;
		for(int i = 2;i <= n; ++i){
			if(vis[i]) continue;
			if(tot & 1) a[l++] = i,tot++;
			else a[r--] = i,tot++;
		}
		for(int i = 1;i <= n; ++i) cout<<a[i]<<' ';
		cout<<'\n';
	}
}

T2 树上游戏

[ARC116E] Spread of Information

一眼看上去像是个dp,但是好像不太行。

使最大值最小,考虑一下二分答案+贪心。

二分答案,贪心构造,看是否可以用k个点使得最大值\(\le mid\)

我们可以发现,对于深度最深的叶子节点,选择它的mid级祖先一定不劣。

所以可以贪心构造

设\(a_x\)表示\(x\)到以\(x\)为根的子树内最远的未被覆盖的点的距离。

\(b_x\)表示\(x\)到以\(x\)为根的子树内最远的被选的点的距离

\[a_x = \max{a_y+1}\quad b_x = \min{b_y+1}\quad y\in son_x \]

如果\(a_x=mid\)说明该点必选,那么\(a_x = -\infty,b_x = 0\),计数器加一

如果\(b_x>mid\),那么以\(x\)为根的子树所选的点无法覆盖自己,需要祖先覆盖。

如果\(a_x+b\_x\le mid\)时,那么以\(x\)为根的子树所选的点可以覆盖自己,\(a_x=-\infty\)

注意特判根节点。

点此查看代码
#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)
using ll=long long;using ull=unsigned long long;using db = double;
#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
const int N = 2e5 + 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,k,a[N],b[N],len,num;
void dfs(int x,int fa){
	a[x] = -0x3f3f3f3f;
	b[x] = 0x3f3f3f3f;
	for(int i = head[x]; i;i = edge[i].next){
		int y = edge[i].to;
		if(y == fa)continue;
		dfs(y,x);
		a[x] = max(a[x],a[y]+1);
		b[x] = min(b[x],b[y]+1);
	}
	if(b[x] > len) a[x] = max(a[x],0);
	if(a[x] + b[x] <= len) a[x] = -0x3f3f3f3f;
	if(a[x] == len) a[x] = -0x3f3f3f3f,b[x] = 0,num++;
}
inline bool check(int mid){
	len = mid,num = 0;
	dfs(1,0);
	num += a[1] >= 0;
	return (num <= k);
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
	cin>>n>>k;
	for(int i = 1,u,v;i < n; ++i) cin>>u>>v,add(u,v),add(v,u);
	int l = 1,r = n,ans = 0;
	while(l <= r){
		int mid = (l+r)>>1;
		if(check(mid)) ans = mid,r = mid - 1;
		else l = mid + 1;
	}
	cout<<ans<<'\n';
}

T3 Ball Collector

[ABC302Ex] Ball Collector

考虑套路,将\(a_i\)与\(b_i\)连边。

我们发现,如果答案是点数减去连通块为树的个数。

可撤销并查集维护

点此查看代码
#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)
using ll=long long;using ull=unsigned long long;using db = double;
#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
const int N = 2e5 + 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,a[N],b[N],num[N];
int dis[N],fa[N],siz[N],ans[N],res = 0;
#define mk make_pair
pair<int,int> sta[N];
int top,tag[N];
int get_fa(int x){return (fa[x] == x?x:get_fa(fa[x]));}
inline void merge(int x,int y){
    x = get_fa(x),y = get_fa(y),top++;
    if(x == y){
        if(num[x] == siz[x]-1) res++,tag[top] = 1;
        num[x]++,sta[top] = mk(-1,x);
    }
    else{
        if(siz[x] > siz[y]) swap(x,y);
        if(num[x] == siz[x] - 1 || num[y] == siz[y] - 1) res++,tag[top] = 1;
        siz[y] += siz[x],fa[x] = y,sta[top] = mk(x,y);
        num[y] += num[x] + 1;
    }
}
inline void undo(int rest){
    while(top > rest){
        if(sta[top].first == -1) num[sta[top].second]--;
        else{
            int x = sta[top].first,y = sta[top].second;
            fa[x] = x,siz[y] -= siz[x],num[y] -= num[x]+1;
        }
        if(tag[top]) res--;
        tag[top] = 0;sta[top] = mk(0,0);
        top--;
    }
}
void dfs(int x,int f){
    int now = top;
    merge(a[x],b[x]);
    ans[x] = res;
    for(int i = head[x]; i;i = edge[i].next){
        int y = edge[i].to;
        if(y == f) continue;
        dfs(y,x);
    }
    undo(now);
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    cin>>n;
    for(int i = 1;i <= n; ++i) cin>>a[i]>>b[i];
    for(int i = 1,u,v;i < n; ++i) cin>>u>>v,add(u,v),add(v,u);
    for(int i = 1;i <= n; ++i) fa[i] = i,siz[i] = 1;
    dfs(1,0);
    for(int i = 2;i <= n; ++i) cout<<ans[i]<<' ';
}

T4 满穗

[NWRRC2017] Joker

难题,用分块维护凸壳,不会打,跳了

赛时太糖了,没有磕T2T3反而磕了T4。
学会了可撤销并查集,算是一个不错的东西。

标签:FILE,int,top,long,集训,num,暑假,using,csp
From: https://www.cnblogs.com/hzoi-Cu/p/18323793

相关文章

  • ssy中学暑假集训学习笔记
    7.25集训第二天今天我们学了博弈论相关题目,但是在做相关题目前,我们先明确几个基本的知识点:mex运算:给定一个集合,该集合中不存在的最小自然数即为该序列的mex。举个例子:对于集合{\(0\),\(1\),\(1\),\(2\),\(4\)},他的mex即为\(3\)。SG函数:我们先建立一个DAG,从出度为\(0\)的节......
  • 暑假集训CSP提高模拟7
    暑假集训CSP提高模拟7组题人:@KafuuChinocpp|@Chen_jr\(T1\)P122.Permutations&Primes\(20pts\)原题:CF1844BPermutations&Primes假的构造策略,拿到了\(20pts\)。若\(n\)为奇数,则将\(1\)放在\(\left\lceil\frac{n}{2}\right\rceil\)的位置上,前一半......
  • 「模拟赛」暑期集训CSP提高模拟5(7.22)
    \(140pts,Rank24\)题目列表:简单的序列简单的字符串简单的困难的图论简单的序列\(100pts\)题意:gtm1514不喜欢序列。但是一天他拿到了一个序列。这个序列非常杂乱,于是gtm1514想要整理一下这个序列。但是由于他非常的菜,他只会进行一个操作:选择一个\(ai\),把它变......
  • CSP 2023 Round 2 游记
    Day?最近\(WHK\)下滑严重,月考排名掉到了\(50\)多了,想着等着这次\(CSP\)完就先退役,也就没想着拿奖去复习。Day0考前周五没怎么搞\(OI\),学校作业多到爆炸,晚自习老师一直讲课,都要睡着了,完事和WSL一起散散步就出校门了,结果WSL却跑回去跑800,说是为了运动会(,卷神。Day1-......
  • CSP 模拟 4
    T1WhiteandBlack原题ARC148CLightsOutonTree最小和无解都不用管,不能下改上,所以从上往下,遇到就反转。一定的观察后发现,当这个点的颜色与父亲不同时,会有贡献,然后直接就做完了。点击查看代码#include<bits/stdc++.h>typedeflonglongll;typedefunsignedlonglong......
  • CSP 模拟 3
    joke3579场,T1abc猜想([ARC111A]SimpleMath2)直接\(\bmod\c\),很难做,不难想到换一个和\(c\)有关的模数,\(c^2\)很好,因为它除以\(c\)再模上\(c\)后为\(0\)。求\(x=a^b(\bmod\c^2)\),\(a^b=k\cdotc^2+x\),除以\(c\)模\(c\)后,前面那个东西没了,只剩\(x\),所以答......
  • ccfcsp 201803.2 碰撞的小球 100分代码
    本题是一道小模拟规模小难度在碰撞检测在写模拟题时的思路应该是先找到应该储存的信息是哪些,抽象出来,应该模拟的方法是哪些。类似oop。includeusingnamespacestd;constintL=1000;structball{intp;chard=1;//只可能为1或-1,表示方向}b[L+1];intmain(){int......
  • 「模拟赛」暑期集训CSP提高模拟4(7.21)
    很祭的一次比赛,啥也不会。题目列表:A.WhiteandBlackB.WhiteandWhiteC.BlackandBlackD.BlackandWhiteA.WhiteandBlack\(0pts\)题意:给你一颗树,树根为1,初始所有点都是白色,每次询问给出一个点集,若把点集中的点全部染成黑色,问至少需要翻转多少个节点才能使整......
  • 2024暑假集训测试10
    前言比赛链接。这回挂的比较少,就T2唐了太长时间导致T4暴力没打完挂了\(60\),不过T4暴力给的非常多,但也并不好打,T3赛后因数据水安排重测,重测后还往上涨了\(2\)名,因为我的解法就是本着\(60pts\)部分分去的,没有卡掉我。T1花间叔祖原题。考虑另\(P=2\)则\(an......
  • 暑假集训CSP提高模拟6
    赛时在\(T2\)浪费时间太多,导致\(T4\)暴力没时间想了,总是想把\(T2\)这种题当大型分讨来做A.花间叔祖[ARC148A]modM观察性质可以发现,答案要么是1,要么是2,把是1的情况找出来剩下的就是2。考虑什么时候是1,如果一个数列模上一个数结果相同,那么他们的差一定是这个模数的整......