A.不相邻集合

考虑值域上连续的段,可以发现连续的长度为 \(x\) 的段的贡献必定为 \(\lceil{\frac{x}{2}}\rceil\)

考虑并查集维护值域连续的段的大小,每次询问求出全部连续段的 \(\lceil{\frac{size}{2}}\rceil\) 之和即为答案

合并操作:在值域上加入 \(x\),尝试合并 \(x-1\) 与 \(x+1\)

复杂度不对,考虑优化

  1. 记一个关于值域的 \(vis\),若单次插入不改变 \(vis\),则答案不变
  2. 每次在并查集上合并时直接统计答案,先减去两个分别的答案,再加上总和的答案
  3. 记得新加入单点时的贡献为 \(\lceil{\frac{1}{2}}\rceil=1\)
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define void inline void
// #define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define test(i) cout<<"test: "<<i<<endl
#define testp(i,j) cout<<i<<" "<<j<<endl
#define testd(i) cout<<i<<" "
#define end cout<<"\n"
#define div <<" "<<
#else
#define test(i)
#define testp(i,j)
#define testd(i)
#define end false
#define div ,
#endif
template<typename T>
void read(T& x){
x=0;bool sym=0;char c=getchar();
while(!isdigit(c)){sym^=(c=='-');c=getchar();}
while(isdigit(c)){x=x*10+c-48;c=getchar();}
if(sym)x=-x;
}
template<typename T,typename... Args>
void read(T& x,Args&... args){
read(x);read(args...);
}
vector<int>has;
int ans=0;
class dsu{
public:
int fa[500001],siz[500001];
void reset(int n){
for(int i=1;i<=n;++i){
fa[i]=i;
siz[i]=1;
}
}
int find(int id){
if(fa[id]==id) return id;
fa[id]=find(fa[id]);
return fa[id];
}
void connect(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy){
fa[fx]=fy;
ans-=(siz[fy]+1)/2+(siz[fx]+1)/2;
siz[fy]+=siz[fx];
ans+=(siz[fy]+1)/2;
}
}
};
dsu d;
int a[300001];
bool vis[500001];
int tot,lastans=0;
int main(){
int n;
read(n);d.reset(500000);
for(int i=1;i<=n;++i){
read(a[i]);
if(!vis[a[i]]){
vis[a[i]]=true;
has.push_back(a[i]);
ans++;
if(vis[a[i]-1]){
d.connect(a[i],a[i]-1);
}
if(vis[a[i]+1]){
d.connect(a[i],a[i]+1);
}
}
cout<<ans<<' ';
}
}

B.线段树

设 \(f(n,x)\) 表示对从长度为 \(n\) 的连续段建立线段树(即有 \(n\) 个叶节点),根节点的值为 \(x\),左儿子的值为 \(2x\),右儿子的值为 \(2x+1\) 的情况下的全部节点权值和

可以发现对于根节点儿子的权值,相对于根节点权值的变化只有两种:即乘以一个系数或者加上若干值,也即 \(f(n,x)\) 是关于 \(x\) 的一次函数

设 \(f(n,x)=k_{n}x+b_{n}\),考虑到我们在对此线段树向下分治的时候,总会有 \(\lceil{\frac{n}{2}}\rceil\) 长度的区间被分配到左儿子,\(\lfloor{\frac{n}{2}}\rfloor\) 长度的区间被分配到右儿子,也就是说:

\[f(n,x)=f(\lceil{\frac{n}{2}}\rceil,2x)+f(\lfloor{\frac{n}{2}}\rfloor,2x+1)+x
\]

根据上设,可得

\[k_{n}x+b_{n}=k_{\lceil{\frac{n}{2}}\rceil}2x+b_{\lceil{\frac{n}{2}}\rceil}+k_{\lfloor{\frac{n}{2}}\rfloor}(2x+1)+b_{\lfloor{\frac{n}{2}}\rfloor}+x
\]

解这个方程,得到

\[\begin{cases}k_{n}=2k_{\lceil{\frac{n}{2}}\rceil}+2k_{\lfloor{\frac{n}{2}}\rfloor}+1\\b_{n}=b_{\lceil{\frac{n}{2}}\rceil}+k_{\lfloor{\frac{n}{2}}\rfloor}+b_{\lfloor{\frac{n}{2}}\rfloor}\end{cases}
\]

关于这个递推式的初态,可以感性理解

  • 当 \(n=1\) 时,线段树中只有一个节点 \(x\),因此 \(k_{1}=1,b_{1}=0\)
  • 当 \(n=2\) 时,线段树中只有三个节点 \(x,2x,2x+1\),和为 \(5x+1\),因此 \(k_{1}=5,b_{1}=1\)

其余开 map 记搜即可

如果你们 WA60 也有可能是 build() 里的 id 忘记取模了

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
template<typename T>
inline T read(){
T x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch-'0');
ch=getchar();
}
return x*f;
}
template<typename T>
inline T read(T&a){
T x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch-'0');
ch=getchar();
}
return a=x*f;
}
template<typename T>
inline void write(T x){
if(x<0)x*=-1,putchar('-');
if(x>9)write(x/10);
putchar(x%10+'0');
return;
}
const int p=1e9+7;
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)%p;
}
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))%p;
}
int build(int id,int l,int r,int L,int R){
if(l>R or r<L) return 0;
if(L<=l and r<=R){
return (k(r-l+1)*id%p+b(r-l+1))%p;
}
int mid=(l+r)/2;
return (build((id*2)%p,l,mid,L,R)+build((id*2+1)%p,mid+1,r,L,R))%p;
}
signed main(){
int T;read(T);
while(T--){
int n,l,r;
read(n);read(l);read(r);
write(build(1,1,n,l,r)%p);putchar('\n');
}
}

C.魔法师

题目需要我们求 \(\max(a_{i}+a_{j},b_{i}+b_{j})\)

分类讨论,注意到 \(a_{i}+a_{j}\gt b_{i}+b_{j}\) 的时候,只需要令 \(a_{i}-b_{i}\gt b_{j}-a_{j}\) 即可,此时的答案即为 \(a_{i}+a_{j}\),否则,当 \(a_{i}-b_{i}\le b_{j}-a_{j}\) 时,答案便为 \(b_{i}+b_{j}\),这样我们就去除了 \(\max\) 符号

因此我们尝试对每个 \(u_{i}=a_{i}-b_{i},v_{i}=b_{i}-a_{i}\) 进行比较. 现在我们可以把问题转化为求满足 \(u_{i}\gt v_{j}\) 的 \((i,j)\) 的 \(a_{i}+a_{j}\) 最小值,或者满足 \(u_{i}\le v_{j}\) 的 \((i,j)\) 的 \(b_{i}+b_{j}\) 最小值,在两者中再取一个最小值即为答案.

考虑对 \(u,v\) 建一颗权值线段树,考虑到,当 \(i\) 在左子树,\(j\) 在右子树时,一定有 \(u_{i}\le v_{j}\),因此 \((i,j)\) 可以用于更新父亲节点 \(b_{i}+b_{j}\) 的最小值,反之同理,而我们需要的整体最小值,要么就是从子节点继承上来的答案,要么就是该节点的 \(i\) 在左子树,\(j\) 在右子树时的情况或者 \(j\) 在左子树,\(i\) 在右子树时贡献的情况,可以发现这样做正好覆盖了全部合法的 \((i,j)\)

因为在 \((i,j)\) 中,一定有前者为法杖,后者为咒语。因此在增加操作中,遇到法杖 \(i\) 则在 \(a-b\) 位置插入节点 \((a_{i},b_{i})\),遇到咒语 \(j\) 则在 \(b-a\) 位置插入节点 \((a_{j},b_{j})\),然后按顺序向上更新每层法杖的 \(a,b\) 最小值,咒语的 \(a,b\) 最小值,然后在当前节点用左子树法杖,右子树咒语,或者左子树咒语,右子树法杖的最小值分别计算贡献并取最小值即可

关于删除操作,注意到同一个叶节点下方可能会有多个 \((a,b)\),因此考虑建树套树,简化一点开个 set 维护,因为我们需要分别统计四个最值,因此对每个叶节点开四个 set,分别以不同关键字排序,统计答案的时候取首位维护最小值,删除的时候直接暴力搜索删除,记得删除之后要将该节点统计信息清空后重新统计一遍,防止原先较大的答案未被覆盖导致的错误.

处于空间考虑,我们只需要对每个叶节点开一个 set,因此考虑将 set 建在外面,线段树里面只存储 set 的编号来处理. 由于 \(a-b\) 可能存在负数,因此需要整体偏移,鉴于 \(a,b\in[0,2.5e5]\),偏移量为 \(0-2.5e5=-2.5e5\),线段树范围为 \(2.5e5-0-(-2.5e5)=5e5\),最大值不超过 \(2.5e5+2.5e5=5e5\),不用开 long long

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
template<typename T>
void read(T& x){
x=0;bool sym=0;char c=getchar();
while(!isdigit(c)){sym^=(c=='-');c=getchar();}
while(isdigit(c)){x=x*10+c-48;c=getchar();}
if(sym)x=-x;
}
template<typename T,typename... Args>
void read(T& x,Args&... args){
read(x);read(args...);
}
#define tests int cases;read(cases);while(cases--)
#define pb push_back
int Q,T;
const int N=5e5+10,dx=N/2;
const int inf=1e8;
int lastans=0;
struct node{
int a,b;
bool operator <(const node &A)const{
if(a==A.a) return b<A.b;
return a<A.a;
}
};
struct node2{
int a,b;
bool operator <(const node2 &A)const{
if(b==A.b) return a<A.a;
return b<A.b;
}
};
struct setpair{
set<node> pa,qa;
set<node2> pb,qb;
};
vector<setpair>store;
namespace Stree{
#define tol (id*2)
#define tor (id*2+1)
#define mid(l,r) mid=(l+r)/2
struct tree{
int l,r;
int store_id;
int minap,minaq,minbp,minbq;
int minansa,minansb;
}t[4*N];
void pushup(int id){
t[id].minap=inf;
t[id].minaq=inf;
t[id].minbp=inf;
t[id].minbq=inf;
t[id].minansa=t[id].minansb=inf;
if(t[tol].l){
t[id].minap=min(t[tol].minap,t[id].minap);
t[id].minaq=min(t[tol].minaq,t[id].minaq);
t[id].minbp=min(t[tol].minbp,t[id].minbp);
t[id].minbq=min(t[tol].minbq,t[id].minbq);
t[id].minansa=min(t[tol].minansa,t[id].minansa);
t[id].minansb=min(t[tol].minansb,t[id].minansb);
}
if(t[tor].l){
t[id].minap=min(t[tor].minap,t[id].minap);
t[id].minaq=min(t[tor].minaq,t[id].minaq);
t[id].minbp=min(t[tor].minbp,t[id].minbp);
t[id].minbq=min(t[tor].minbq,t[id].minbq);
t[id].minansa=min(t[tor].minansa,t[id].minansa);
t[id].minansb=min(t[tor].minansb,t[id].minansb);
}
if(t[tol].l and t[tor].l){
t[id].minansa=min({t[tol].minansa,t[tor].minansa,t[tol].minaq+t[tor].minap});
t[id].minansb=min({t[tol].minansb,t[tor].minansb,t[tol].minbp+t[tor].minbq});
}
}
void build(int id,int l,int r){
t[id].l=l;t[id].r=r;
t[id].minap=inf,t[id].minaq=inf;
t[id].minbp=inf,t[id].minbq=inf;
t[id].minansa=inf;t[id].minansb=inf;
if(l==r){
store.push_back({});
t[id].store_id=(int)store.size()-1;
return;
}
int mid(l,r);
build(tol,l,mid);
build(tor,mid+1,r);
}
void update(int id,bool isp){
if(!store[t[id].store_id].pa.empty()) t[id].minap=store[t[id].store_id].pa.begin()->a;
else t[id].minap=inf;
if(!store[t[id].store_id].pb.empty()) t[id].minbp=store[t[id].store_id].pb.begin()->b;
else t[id].minbp=inf;
if(!store[t[id].store_id].qa.empty()) t[id].minaq=store[t[id].store_id].qa.begin()->a;
else t[id].minaq=inf;
if(!store[t[id].store_id].qb.empty()) t[id].minbq=store[t[id].store_id].qb.begin()->b;
else t[id].minbq=inf;
t[id].minansa=min(inf,t[id].minap+t[id].minaq);
t[id].minansb=min(inf,t[id].minbp+t[id].minbq);
}
void update2(int id,bool isp,int a,int b){
if(isp){
t[id].minap=min(t[id].minap,a);
t[id].minbp=min(t[id].minbp,b);
}
else{
t[id].minaq=min(t[id].minaq,a);
t[id].minbq=min(t[id].minbq,b);
}
t[id].minansa=min(inf,t[id].minap+t[id].minaq);
t[id].minansb=min(inf,t[id].minbp+t[id].minbq);
}
void change(int id,int pos,bool isp,int a,int b){
if(t[id].l==t[id].r){
if(isp){
store[t[id].store_id].pa.insert({a,b});
store[t[id].store_id].pb.insert({a,b});
}
else{
store[t[id].store_id].qa.insert({a,b});
store[t[id].store_id].qb.insert({a,b});
}
update2(id,isp,a,b);
return;
}
if(pos<=t[tol].r) change(tol,pos,isp,a,b);
else change(tor,pos,isp,a,b);
pushup(id);
}
void remove(int id,int pos,int isp,int a,int b){
if(t[id].l==t[id].r){
if(isp){
auto it1=store[t[id].store_id].pa.lower_bound(node{a,b});
auto it2=store[t[id].store_id].pb.lower_bound(node2{a,b});
if(it1!=store[t[id].store_id].pa.end() and it1->a==a and it1->b==b){
store[t[id].store_id].pa.erase(it1);
store[t[id].store_id].pb.erase(it2);
}
}
else{
auto it1=store[t[id].store_id].qa.lower_bound(node{a,b});
auto it2=store[t[id].store_id].qb.lower_bound(node2{a,b});
if(it1!=store[t[id].store_id].qa.end() and it1->a==a and it1->b==b){
store[t[id].store_id].qa.erase(it1);
store[t[id].store_id].qb.erase(it2);
}
}
update(id,isp);
return;
}
if(pos<=t[tol].r) remove(tol,pos,isp,a,b);
else remove(tor,pos,isp,a,b);
pushup(id);
}
int solve(){
return min(t[1].minansa,t[1].minansb);
}
}
using namespace Stree;
signed main(){
read(Q,T);
build(1,1,N);
for(int i=1;i<=Q;++i){
int op,t,a,b;read(op,t,a,b);
if(T==1){
a^=lastans;b^=lastans;
}
if(op==1){
if(t==0){
change(1,a-b+dx,true,a,b);
}
else{
change(1,b-a+dx,false,a,b);
}
}
else{
if(t==0){
remove(1,a-b+dx,true,a,b);
}
else{
remove(1,b-a+dx,false,a,b);
}
}
int res=solve();
cout<<(lastans=(res==inf?0:res))<<endl;
}
}

[29] CSP模拟2的更多相关文章

  1. Nescafe #29 NOIP模拟赛

    Nescafe #29 NOIP模拟赛 不知道这种题发出来算不算侵权...毕竟有的题在$bz$上是权限题,但是在$vijos$似乎又有原题...如果这算是侵权的话请联系我,我会尽快删除,谢谢~ 今天开 ...

  2. csp模拟赛低级错误及反思

    \(csp\)模拟赛低级错误及反思. 1.没开\(longlong\). 反思:注意数据类型以及数据范围. 2.数组越界(前向星数组未开两倍,一题的数据范围应用到另一题上,要开两倍的写法为开两倍数组) ...

  3. 2018.06.29 NOIP模拟 Gcd(容斥原理)

    Gcd 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出n个正整数,放入数组 a 里. 问有多少组方案,使得我从 n 个数里取出一个子集,这个子集的 gcd 不为 1 ,然后我再从 ...

  4. 9.27下午考试(Nescafé 29杯模拟赛)

    140pts(100+30+10)Rank3 前几天还考了一场,AK,没什么好总结的,所以就没写博客. 炸: T2,模拟退火突然不会了,写个状压dp,排序边的时候sort的N而不是M. 这个坑经常出! ...

  5. 19.7.29 NOIP模拟10

    话说这次三道考试题直接可以连成一个段子:我一个辣鸡,连模板都不会打,只能跪倒在大佬面前; T1 辣鸡 但是我实在是太辣鸡了,最后干的T1,时间不够用,连暴力都没打对,无奈之下交了一个qj程序,60分( ...

  6. 【CSP模拟赛】Freda的迷宫(桥)

    题目描述 Freda是一个迷宫爱好者,她利用业余时间建造了许多迷宫.每个迷宫都是由若干房间和走廊构成的,每条走廊都连接着两个不同的房间,两个房间之间最多只有一条走廊直接相连,走廊都是双向通过.  黄昏 ...

  7. 【csp模拟赛九】--dfs3

    这道题贪心错误:直接dfs就行,枚举新开一个还是往之前的里面塞 贪心代码(80): #include<cstdio> #include<algorithm> #include& ...

  8. 2019.7.29 NOIP模拟测试10 反思总结【T2补全】

    这次意外考得不错…但是并没有太多厉害的地方,因为我只是打满了暴力[还没去推T3] 第一题折腾了一个小时,看了看时间先去写第二题了.第二题尝试了半天还是只写了三十分的暴力,然后看到第三题是期望,本能排斥 ...

  9. @CSP模拟2019.10.16 - T3@ 垃圾分类

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 为了保护环境,p6pou建设了一个垃圾分类器. 垃圾分类器是一个 ...

  10. CSP模拟赛2游记

    这次由于有课迟到30min,了所以只考了70min. 调linux配置调了5min,只剩下65min了. T1:有点像标题统计,但要比他坑一点,而且我就被坑了,写了一个for(int i=1;i< ...

随机推荐

  1. 2024 暑假友谊赛-热身2 (7.12)zhaosang

    E-E https://vjudge.net/problem/AtCoder-diverta2019_b 给你 a, b, c ,n就是问你有多少(ia+jb+k*c)等于n的答案i,j,k任意几个都 ...

  2. Django 文件导入实现方案

    Django文件导入实现方案 by:授客 QQ:1033553122 开发环境   Win 10   Python 3.5.4   Django-2.0.13.tar.gz 官方下载地址: https ...

  3. Activity活动生命相关

    启动与结束 页面跳转: startActivity(new Intent(this,xxxx.class)); 关闭当前界面返回上一界面 finish(); //这里我在使用finish遇到一个问题, ...

  4. 8、IDEA集成Git

    8.1.配置Git忽略文件 8.1.1.忽略文件的原因 在使用 IDE 工具时,会自动生成一些和项目源码无关的文件,所以可以让 Git 忽略这些文件. 此外,把这些无关文件忽略掉,还能够屏蔽不同 ID ...

  5. 【Java】图片上传逻辑

    后台逻辑: 后台服务,用Dubbo框架作为一个文件微服务 package cn.ymcd.aisw.service; import cn.ymcd.aisw.dto.RpcResult; /** * ...

  6. 【XML】Extensible Markup Language 可扩展标记语言

    Extensible Markup Language 可扩展标记语言[XML] 视频资料参考自:https://www.bilibili.com/video/BV1B441117Lu?p=186 其他 ...

  7. 常回家看看之fastbin_attack

    常回家看看之fastbin_attack 原理分析 fastbin属于小堆块的管理,这里说的fastbin_attack大多指glibc2.26之前的手法,因为自glibc2.26以后,glibc迎来 ...

  8. Regardless of the outcome of the Russia-Ukraine war, how can Ukraine avoid paying the weapon fees to the United States after the war?

    According to the agreement between the Ukrainian government and the United States, regardless of the ...

  9. 树莓派3b+ 系统(Raspbian)环境搭建以及配置

    多年前购入树莓派3b+板子一块,一直没时间弄,近期疫情假期在家翻出来打算鼓捣鼓捣. 1.  树莓派系统下载: 链接地址:   https://www.raspberrypi.org/downloads ...

  10. 模拟实现FutureTask

    1.背景 面试官问,,假设让你编写一个FutureTask,你的思路是..... 2.代码 2.1.GuardedObject对象 package com.common; /** * @author ...