首页 > 其他分享 >CSP 模拟 48

CSP 模拟 48

时间:2024-10-16 11:13:00浏览次数:1  
标签:std ch 48 int mid long CSP 模拟 define

A 限速(speed)

对于边权小于等于 \(k\) 的,尽量选大的,对于边权大于 \(k\) 的,尽量选小的,然后按这两个条件排序后 kruskal,如果边权小的能组成生成树,那么答案就是小于等于 \(k\) 的最大的数和第一个大于 \(k\) 的数的较小代价。否则最后的生成树代价就是答案。有六十分的数据边权全部小于等于 \(k\),没判边界值挂 60pts。

B 酒鬼(drunkard)

观察发现要求奇偶性一致,容易想到分讨维护前驱后继得到 83pts 的做法,但是有 \(p_i=1\) 的情况,此时是否出发就很关键,如果没出发,\(p_i=1\) 是不受奇偶限制的。
所以直接考虑时刻维护最早和最晚的出发时间,并且检测相邻的合法性。

  • 当距离大于时间时,不可达,直接不合法。
  • 当前一个不在起点,但它的时间比最早还早,不合法。
  • 当后一个不在起点,此时一定出发了,可以尝试更新最晚出发时间,直接把它当做出发后的第一个到达点更新即可,这样一定不会错。
  • 如果前一个在起点,并且它的时间比最晚早,这时的奇偶性就可以不同,如果不同,更新最早的出发时间,此时合法。
  • 排除掉上述所有情况后,再次根据奇偶性判断是否合法就可以了。

想清楚这些后,这道题就很好做了,这种小模拟的题以后还是要想清楚做出来。

#include<bits/stdc++.h>
#define fi first
#define se second
#define int long long
#define pii std::pair<int,int>
#define eb emplace_back
typedef long long ll;
typedef unsigned long long ull;
std::mt19937 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count());
inline int R(int n){return myrand()%n+1;}
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=2e5+10,inf=1e18;
std::unordered_map<int,int> mp;
int n,m,lates,te[N],minn,maxn=inf;
struct OP{int op,x,t;}o[N];
std::set<pii> s;
inline bool check(pii a,pii b){
	int t=b.fi-a.fi,dis=std::abs(b.se-a.se);
	if(dis>t)return false;
	if(a.se!=1&&a.first<=minn)return false;
	if(b.se!=1)maxn=std::min(maxn,b.fi-b.se+1);
	if(a.se==1&&a.fi<=maxn){
		if(t%2!=dis%2)minn=std::max(minn,a.fi+1);return true;
	}
	if(t%2!=dis%2)return false;
	return true;
}
inline void sub(){
    bool pd=0;
	s.insert({0,1});
	for(int i=1;i<=m;++i){
		char ch[5];std::cin>>ch;
		if(ch[1]=='l'){
			int x,t;std::cin>>x>>t;
			if(pd){continue;}
			if(mp[t])if(mp[t]!=x){pd=1;continue;}
			mp[t]=x;
    		auto it=s.insert({t,x}).first;
			auto zc=it;--zc;
			auto la=*zc,now=*it;
			if(!check(la,now)){pd=1;continue;}
			++it;if(it!=s.end()){
				la=*it;if(!check(now,la)){pd=1;continue;}
			}

		}if(ch[1]=='i'){
			if(pd){std::cout<<"bad\n";continue;}
			std::cout<<minn<<'\n';
		}if(ch[1]=='a'){
			if(pd){std::cout<<"bad\n";continue;}
			if(maxn==inf){std::cout<<"inf\n";continue;}
			std::cout<<maxn<<'\n';
		}
	}
}
signed main(){
    freopen("drunkard.in","r",stdin);freopen("drunkard.out","w",stdout);
    // freopen("in.in","r",stdin);freopen("out.out","w",stdout);
    std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
    std::cin>>n>>m;
    sub();
}

C1 距离(distance)

换题后的 C 题,确实放原题太水了。
首先如果直接看这个式子,大力分讨应该会得到一个树套树或者 CDQ 分治的三个 log 的做法,又复杂又难写,还不优秀,考虑化式子。
切比雪夫距离:\(\max(|x1-x2|,|y1-y2|)\),曼哈顿距离:\(|x1-x2|+|y1-y2|\)。
曼哈顿距离转化:\(|x1-x2|+|y1-y2|=\max\{x1-x2+y1-y2,x1-x2+y2-y1,x2-x1+y1-y2,x2-x1+y2-y1\}=\max(|(x1+y1)-(x2+y2)|,|(x1-y1)-(x2-y2)|)\),就转化成了 \((x+y,x-y)\) 的切比雪夫距离。
同理切比雪夫距离等同于 \((\frac{x+y}{2},\frac{x-y}{2})\) 的曼哈顿距离,证明分讨即可。
如果了解过一定的切比雪夫距离,就会很自然想到化式子了,\(\min(a,b)=a+b-\max(a,b)\),后面一个就是切比雪夫距离了,设 \(p_i=\frac{a_i+b_i}{2},q_i=\frac{a_i-b_i}{2}\),最后需要求:

\[\begin{aligned} |a_i-a_j|+|b_i-b_j|-|p_i-p_j|-|q_i-q_j| \end{aligned} \]

由于点对本来就要乘 \(2\),所以 \(p,q\) 不必除以 \(2\),处理这四个绝对值自然想到分讨,dsuBIT,时间复杂度 \(\mathcal{O}(n\log^2n)\),且常数巨大,不太可能通过 5e5 的数据。
考虑如果在序列上处理绝对值该怎么做,一种就是上树状数组或者线段树分讨,还有一种更加简单,排完序后直接找前面后后面即可,这题也是同理,如果可以使节点的值有序,那么直接查前面和后面即可,\(ans[l,r]=ans[l,mid]+ans[mid+1,r]+sum[mid+1,r]\times cnt[l,mid]-sum[l,mid]\times cnt[mid+1,r]\),如果我们可以一直保留这个序列,答案也就迎刃而解了,放弃 dsu,尝试把节点拍到线段树上,然后从下往上线段树合并即可,根节点就是答案,时间复杂度 \(\mathcal{O}(n\log n)\)。

#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pii std::pair<int,int>
#define eb emplace_back
typedef long long ll;
typedef unsigned long long ull;
const int N=5e5+10,mod=1e9+7;
std::mt19937 myrand(std::chrono::high_resolution_clock::now().time_since_epoch().count());
inline int R(int n){return myrand()%n+1;}
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
inline void Min(int &x,int y){x=std::min(x,y);}
inline void Max(int &x,int y){x=std::max(x,y);}
inline void W(int &x,int y){x=(x+y)%mod;}
int n,temp[4][N],val[4][N],ans[N],tot,ANS[N],root[N],sm[N];
std::vector<int> e[N];
struct TREE{int res,sum,ls,rs,cnt;}t[N*20];
inline void clear(){for(int i=1;i<=tot;++i)t[i]={0,0,0,0,0};tot=0;for(int i=1;i<=n;++i)root[i]=0;}
inline void update(int p){
    t[p].res=t[t[p].ls].res+t[t[p].rs].res+t[t[p].rs].sum*t[t[p].ls].cnt%mod-t[t[p].ls].sum*t[t[p].rs].cnt%mod;
    t[p].sum=(t[t[p].ls].sum+t[t[p].rs].sum)%mod;t[p].cnt=t[t[p].ls].cnt+t[t[p].rs].cnt;
}
inline void insert(int &p,int l,int r,int pos,int x){
    if(!p)p=++tot;
    if(l==r){W(t[p].sum,x),t[p].cnt++;return ;}
    int mid=l+r>>1;if(pos<=mid)insert(t[p].ls,l,mid,pos,x);
    if(pos>mid)insert(t[p].rs,mid+1,r,pos,x);update(p);
}
inline int merge(int a,int b,int l,int r){
    if(!a||!b)return a|b;
    if(l==r){W(t[a].res,t[b].res),W(t[a].sum,t[b].sum),t[a].cnt+=t[b].cnt;return a;}
    int mid=l+r>>1;
    t[a].ls=merge(t[a].ls,t[b].ls,l,mid);
    t[a].rs=merge(t[a].rs,t[b].rs,mid+1,r);
    update(a);return a;
}
inline void dfs(int x,int fa,int id){
    insert(root[x],1,n,val[id][x],temp[id][val[id][x]]);
    for(int v:e[x]){
        if(v==fa)continue;
        dfs(v,x,id);
        root[x]=merge(root[x],root[v],1,n);
    }
    ans[x]=t[root[x]].res;
}
signed main(){
    freopen("in.in","r",stdin);freopen("out.out","w",stdout);
    freopen("distance.in","r",stdin);freopen("distance.out","w",stdout);
    std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
    n=read();for(int i=1;i<n;++i){int u=read(),v=read();e[u].eb(v);e[v].eb(u);}
    for(int i=1;i<=n;++i){
        int a=read(),b=read();val[0][i]=a,val[1][i]=b,val[2][i]=a+b,val[3][i]=a-b;
        temp[0][i]=a,temp[1][i]=b,temp[2][i]=a+b,temp[3][i]=a-b;
    }
    for(int i=0;i<4;++i){
        std::sort(temp[i]+1,temp[i]+n+1);int cnt=std::unique(temp[i]+1,temp[i]+n+1)-temp[i]-1;
        for(int j=1;j<=n;++j)val[i][j]=std::lower_bound(temp[i]+1,temp[i]+cnt+1,val[i][j])-temp[i];
    }
    dfs(1,0,0);for(int i=1;i<=n;++i)ANS[i]=ans[i]*2%mod;clear();
    dfs(1,0,1);for(int i=1;i<=n;++i)W(ANS[i],ans[i]*2);clear();
    dfs(1,0,2);for(int i=1;i<=n;++i)W(ANS[i],-ans[i]);clear();
    dfs(1,0,3);for(int i=1;i<=n;++i)W(ANS[i],-ans[i]),W(ANS[i],mod),std::cout<<ANS[i]<<'\n';
}

赛时两个 dfs 函数的名写错了,挂了 60pts。

C2 单峰数列(peak)

原题解中的 C 题,大体就是拿线段树维护一个序列区间的单调性,支持区间加,没有任何深意。

D 选拔方案

不会

标签:std,ch,48,int,mid,long,CSP,模拟,define
From: https://www.cnblogs.com/Ishar-zdl/p/18469441

相关文章

  • CSP2024 前集训:csp-s模拟11
    前言T1挂了,后面几道赛时都不那么可做,T2读假题了浪费太多时间,T3没调出来。T4是原,但是整个机房只有一个人当时改了,所以还是没人写,因为T4是原,还加了个T5,也不太可做。T1玩水对于一个点\((i,j)\),若\(s_{i+1,j}=s_{i,j+1}\)则称其为分点,若一个分店后面还有分点或两个分......
  • java模拟量子加密,特别是基于量子密钥分发(QKD)的加密,是一种利用量子力学原理来保证信息
    本人详解作者:王文峰,参加过CSDN2020年度博客之星,《Java王大师王天师》公众号:JAVA开发王大师,专注于天道酬勤的Java开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯山峯转载说明:务必注明来源(注明:作者:王文峰哦)java模拟量子......
  • 信息安全工程师(48)网络物理隔离技术原理与应用
    前言    网络物理隔离技术是一种网络安全技术,其核心原理是通过物理方式将网络或网络设备分隔开来,以确保数据安全、降低风险并提升系统的整体安全性。一、网络物理隔离技术原理物理断开:网络物理隔离技术通过物理设备和传输介质将网络资源分离,确保不同网络之间无任......
  • [2023 CSP-J]题目思考与反思
    小Y的桌子上放着\(n\)个苹果从左到右排成一列,编号为从\(1\)到\(n\\\)。小苞是小Y的好朋友,每天她都会从中拿走一些苹果。\(\\\)每天在拿的时候,小苞都是从左侧第\(1\)个苹果开始、每隔\(2\)个苹果拿走\(1\)个苹果。随后小苞会将剩下的苹果按原先的顺序重新排成一......
  • 2024.10.15 模拟赛
    2024.10.15模拟赛T1count简要题意给定一个长度为\(n\)的数组求其中正整数数量,\(n≤100\)solution哇,还是太难了输入的时候如果是正数就cnt++输出\(cnt\)即可人机题,不放代码了T2sigma简要题意给定\(n\)个双端队列,其中第\(i\)个队列内有\(c_i\)个整数元素。......
  • 2024.10.12 模拟赛
    2024.10.12模拟赛T1delete简要题意给定长度为\(n\)的数列\(a_i\),每次操作需要选择\([l,r]\),满足\(a_l,a_{l+1},...a_{r}\)按位与的结果为\(0\),然后删去\([l,r]\),删去后左边和右边合并起来。问最多能合并多少次。\(n≤63,a_i≤63\)solution显然的,由于这个操作是按......
  • P2480 [SDOI2010] 古代猪文
    简单数学题。显然答案是\(g^{\sum_{d|n}C_n^d}\)。考虑到\(mod\)是质数,所以\(g^{mod-1}\equiv1\pmod{mod}\),那么考虑算出指数模上\(mod-1\)。注意到\(mod-1\)并不是质数,显然可以质因数分解后CRT合并。于是就做完了。Code#include<iostream>#include<ioman......
  • 多校A层冲刺NOIP2024模拟赛07
    rank7,T1100pts,T20pts,T370pts,T416ptsaccoder上rank31,同分限速(speed)签,糖。打的\(O(m\logV)\)的。考虑分类讨论,有两种情况。最大值是由最小的转化过来的,那么就是看边权\(\lek\)的是否可以构成一颗最大生成树,时间复杂度\(O(m\logm)\)最大值是由更大的减下来的,发现......
  • 多校A层冲刺NOIP2024模拟赛07
    多校A层冲刺NOIP2024模拟赛07\(T1\)A.限速(speed)\(40pts\)设最终保留的边的权值构成的集合为\(S\)。那么其贡献为\(\begin{cases}k-\max\limits_{x\inS}\{x\}&\max\limits_{x\inS}\{x\}\lek\\\sum\limits_{x\inS}[x>k]\times(x-k)&\max......
  • Leetcode 1489. 找到最小生成树里的关键边和伪关键边
    1.题目基本信息1.1.题目描述给你一个n个点的带权无向连通图,节点编号为0到n-1,同时还有一个数组edges,其中edges[i]=[fromi,toi,weighti]表示在fromi和toi节点之间有一条带权无向边。最小生成树(MST)是给定图中边的一个子集,它连接了所有节点且没有环,而且这些边......