『模拟赛』csp-s模拟2
『模拟赛』csp-s模拟1
挂分日寄:104pts
非常好测试数据+重新评测,使我库库掉RK。
T1 不相邻集合
赛时乱糊了个
⾸先不相邻集合中不能有两个相同的数,所以每个数只有第⼀次出现是有⽤的。
考虑到一段连续的数
所以只需要维护最长连续子段即可。
可以使用并查集维护,对于一个数
但是每次查询都
每次在并查集上合并时直接统计答案,先减去两个分别的答案,再加上总和的答案即可。
int n,m,a[N],ans=0;
int vis[N];
struct DSU{
int fa[N],siz[N];
void init(){
for(int i=1;i<=500010;i++){
fa[i]=i,siz[i]=1;
}
}
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void unionn(int x,int y){
x=find(x),y=find(y);
if(x==y) return ;
if(siz[x]<siz[y]) swap(x,y);
fa[y]=x;
ans-=ceil((float)siz[x]/2)+ceil((float)siz[y]/2);
siz[x]+=siz[y];
ans+=ceil((float)siz[x]/2);
}
}dsu;
signed main(){
n=rd;
for(int i=1;i<=n;i++) a[i]=rd;
dsu.init();
for(int i=1;i<=n;i++){
if(vis[a[i]]){
printf("%lld ",ans);
continue;
}
vis[a[i]]=1;
ans++;
if(vis[a[i]-1]){
dsu.unionn(a[i]-1,a[i]);
}
if(vis[a[i]+1]){
dsu.unionn(a[i]+1,a[i]);
}
printf("%lld ",ans);
}
return Elaina;
}
T2 线段树
赛时建树+一些小计算亖了...
设
发现其儿子节点的贡献相对于该节点可以表示为该节点的贡献乘以一个系数再加上若干值,即
于是,设
由
可知
解得
const int mod=1e9+7;
const int N=2e6+100;
const int inf=0x7fffffff;
int n,m,ans;
map<int,int> K,B;
int k(int n){
if(n==0) return 0;
if(n==1) return 1;
if(n==2) return 5;
if(K.count(n)) return K[n];
return K[n]=(2*(k((n+1)/2)+k(n/2))+1)%mod;
}
int b(int n){
if(n==0) return 0;
if(n==1) return 0;
if(n==2) return 1;
if(B.count(n)) return B[n];
return B[n]=(b((n+1)/2)+b(n/2)+k(n/2))%mod;
}
int work(int rt,int l,int r,int ql,int qr){
if(l>qr || r<ql) return 0;
if(ql<=l&&r<=qr){
return (k(r-l+1)*(rt%mod)%mod+b(r-l+1)%mod)%mod;
}
int mid=(l+r)>>1;
return work(rt<<1,l,mid,ql,qr)+work(rt<<1|1,mid+1,r,ql,qr);;
}
signed main(){
int T=rd;
while(T--){
int n=rd,x=rd,y=rd;
ans=work(1,1,n,x,y)%mod;
printf("%lld\n",ans);
}
return Elaina;
}
T3 魔法师
赛时考虑用平衡树维护..没时间亖了.改为数组模拟(纯暴力)。
贺题解
对于法杖
具体实现:
得GGrun真传,可以用线段树套multiset,省的建四棵树了。
插入就是直接 insert
;
删除就先 lower_bound
找一下,找到就 erase
;
取最小值时因为set内部是升序排列的,所以直接返回 *set.begin()
即可。
有一点要注意插入时因为不知道差值的正负因此要以一个基准为零点。
int n,m;
#define lson (rt<<1)
#define rson (rt<<1|1)
const int B=25e4;
int ans[N],num[N][2][2];
multiset<int> s[500100][2][2];
void add(int rt,int l,int r,int pos,int a,int b,int opt){
if(l==r){
if(!s[l][0][0].size())
s[l][0][0].insert(1e8),
s[l][1][0].insert(1e8),
s[l][0][1].insert(1e8),
s[l][1][1].insert(1e8);
if(opt<0){
auto itpos=s[l][-opt-1][0].lower_bound(a);
s[l][-opt-1][0].erase(itpos);
itpos=s[l][-opt-1][1].lower_bound(b);
s[l][-opt-1][1].erase(itpos);
}else{
s[l][opt-1][0].insert(a),
s[l][opt-1][1].insert(b);
}
num[rt][0][0]=*s[l][0][0].begin(),//p a
num[rt][0][1]=*s[l][0][1].begin(),//p b
num[rt][1][0]=*s[l][1][0].begin(),//q a
num[rt][1][1]=*s[l][1][1].begin();//q b
ans[rt]=min(num[rt][0][1]+num[rt][1][1],num[rt][1][0]+num[rt][0][0]);
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) add(lson,l,mid,pos,a,b,opt);
if(pos>mid) add(rson,mid+1,r,pos,a,b,opt);
num[rt][0][0]=min(num[lson][0][0],num[rson][0][0]),
num[rt][0][1]=min(num[lson][0][1],num[rson][0][1]),
num[rt][1][0]=min(num[lson][1][0],num[rson][1][0]),
num[rt][1][1]=min(num[lson][1][1],num[rson][1][1]);
ans[rt]=min({ans[lson],ans[rson],num[lson][0][1]+num[rson][1][1],num[lson][1][0]+num[rson][0][0]});
return ;
}
signed main(){
mst(num,0x3f);
mst(ans,0x3f);
int m=rd,T=rd,lst=0;
while(m--){
int opt=rd,t=rd,a=rd,b=rd;
if(T) a^=lst,b^=lst;
int k=(t)?b-a:a-b;
if(opt==1){
add(1,1,5e5,k+B,a,b,t+1);
lst=ans[1]>=1000000?0:ans[1];
}else{
add(1,1,5e5,k+B,a,b,-t-1);
lst=ans[1]>=1000000?0:ans[1];
}
printf("%lld\n",lst);
}
return Elaina;
}
T4 园艺
赛时没时间想DP了,胡乱贪心...呃呃...又亖了...
总结
时间管理大师。
做题策略有问题。
赛后看题解,思路完全不沾边,脑子有问题。
题解有问题。
呃呃,我算是废了。
图
你在想peach.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本