CF1093
题解:
D:
比较显然这个图得是二分图才行
然后每个二分图上的方案是$(2^a+2^b) (a,b是两种颜色的个数)$
E:
我tm就不该先写bitset的
正解和bitset都很好想
因为是个排列,所以所有元素都不同,会有很多性质
bitset就是我们对序列维护一个前缀和表示前i位有哪些数
发现你开不下空间
于是分块一下
复杂度 $n\sqrt{n}+\frac{nm}{32}$
写了没多久卡常数卡了3个小时,然后还没过。。(题解说是不想让它过得。。)
大概是
把bitset换成了手写 循环展开
询问用4个矩形减一减改成两个减一减再做&运算(这个在我本机快了很多 可提交上去影响并不大 不知道为什么)
另外真没发现指针比数组快。。我感觉一般都比数组慢
不过那个4次访问数组把它先用个变量存下来能快一点
cf的机子开不开O2啊。。我这开O2本机跑全是询问的也才7s啊。。
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for(int i=h;i<=t;i++)
#define dep(i,t,h) for(int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define mep(x,y) memcpy(x,y,sizeof(y))
#define mid ((h+t)>>1)
#define ull unsigned long long
namespace IO{
char ss[<<],*A=ss,*B=ss;
IL char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T> void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=(c^);
while (c=gc(),c>&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
char sr[<<],z[]; ll Z,C1=-;
template<class T>void wer(T x)
{
if (x<) sr[++C1]='-',x=-x;
while (z[++Z]=x%+,x/=);
while (sr[++C1]=z[Z],--Z);
}
IL void wer1()
{
sr[++C1]=' ';
}
IL void wer2()
{
sr[++C1]='\n';
}
template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
template<class T>IL T MAX(T x,T y){return x>y?x:y;}
template<class T>IL T MIN(T x,T y){return x<y?x:y;}
};
using namespace IO;
const int N=2.1e5+;
const int M=;
const int l=N/+;
int ans[];
struct Bitset{
ull a[l+];
IL void operator = (const Bitset o)
{
register int i;
for (i=;i+<=l;i+=)
{
a[i]=o.a[i];
a[i+]=o.a[i+];
a[i+]=o.a[i+];
a[i+]=o.a[i+];
a[i+]=o.a[i+];
a[i+]=o.a[i+];
a[i+]=o.a[i+];
a[i+]=o.a[i+];
}
for (;i<=l;i++) a[i]=o.a[i];
}
IL Bitset operator & (Bitset &o)
{
Bitset c;
register int i;
for (i=;i+<=l;i+=)
{
c.a[i]=o.a[i]&a[i];
c.a[i+]=o.a[i+]&a[i+];
c.a[i+]=o.a[i+]&a[i+];
c.a[i+]=o.a[i+]&a[i+];
c.a[i+]=o.a[i+]&a[i+];
c.a[i+]=o.a[i+]&a[i+];
c.a[i+]=o.a[i+]&a[i+];
c.a[i+]=o.a[i+]&a[i+];
}
for (;i<=l;i++) c.a[i]=o.a[i]&a[i];
return c;
}
IL Bitset operator ^ (Bitset &o)
{
Bitset c;
register int i;
for (i=;i+<=l;i+=)
{
c.a[i]=o.a[i]^a[i];
c.a[i+]=o.a[i+]^a[i+];
c.a[i+]=o.a[i+]^a[i+];
c.a[i+]=o.a[i+]^a[i+];
c.a[i+]=o.a[i+]^a[i+];
c.a[i+]=o.a[i+]^a[i+];
c.a[i+]=o.a[i+]^a[i+];
c.a[i+]=o.a[i+]^a[i+];
}
for (;i<=l;i++) c.a[i]=o.a[i]&a[i];
return c;
}
IL int count()
{
int ansl=;
register int i;
for (i=;i+<=l;i+=)
{
ull x0=a[i],x1=a[i+],x2=a[i+],x3=a[i+],x4=a[i+],x5=a[i+],x6=a[i+],x7=a[i+];
ansl+=ans[(x0&)]+ans[(x0>>)&]
+ans[(x0>>)&]+ans[(x0>>)&];
ansl+=ans[(x1&)]+ans[(x1>>)&]
+ans[(x1>>)&]+ans[(x1>>)&];
ansl+=ans[(x2&)]+ans[(x2>>)&]
+ans[(x2>>)&]+ans[(x2>>)&];
ansl+=ans[(x3&)]+ans[(x3>>)&]
+ans[(x3>>)&]+ans[(x3>>)&];
ansl+=ans[(x4&)]+ans[(x4>>)&]
+ans[(x4>>)&]+ans[(x4>>)&];
ansl+=ans[(x5&)]+ans[(x5>>)&]
+ans[(x5>>)&]+ans[(x5>>)&];
ansl+=ans[(x6&)]+ans[(x6>>)&]
+ans[(x6>>)&]+ans[(x6>>)&];
ansl+=ans[(x7&)]+ans[(x7>>)&]
+ans[(x7>>)&]+ans[(x7>>)&];
}
for (;i<=l;i++) ansl+=ans[(a[i]&)]+ans[(a[i]>>)&]
+ans[(a[i]>>)&]+ans[(a[i]>>)&];
return ansl;
}
IL void set(int x,int y)
{
int pos=(x-)/+;
int k=x-pos*;
if (y==) a[pos]|=1ll<<(k-);
else a[pos]|=1ll<<(k-),a[pos]^=1ll<<(k-);
}
};
int a[N],b[N],pos[N],n,m,block,num;
Bitset a1[M],b1[M];
void reset(int x)
{
a1[x]=a1[x-]; b1[x]=b1[x-];
int h1=(x-)*block+,t1=MIN(n,x*block);
rep(i,h1,t1) a1[x].set(a[i],),b1[x].set(b[i],);
}
IL int query(int x,int y)
{
if (!x||!y) return();
int x1=pos[x],y1=pos[y];
Bitset nowa=a1[x1-],nowb=b1[y1-];
rep(i,(x1-)*block+,x) nowa.set(a[i],);
rep(i,(y1-)*block+,y) nowb.set(b[i],);
Bitset nowc=nowa&nowb;
return (nowa&nowb).count();
}
Bitset kong;
IL Bitset get_query1(int x)
{
if (!x) return(kong);
int x1=pos[x];
Bitset nowa=a1[x1-];
rep(i,(x1-)*block+,x) nowa.set(a[i],);
return nowa;
}
IL Bitset get_query2(int x)
{
if (!x) return(kong);
int x1=pos[x];
Bitset nowa=b1[x1-];
rep(i,(x1-)*block+,x) nowa.set(b[i],);
return nowa;
}
IL int query(int l1,int r1,int l2,int r2)
{
Bitset k1=get_query1(l1-),k2=get_query1(r1);
k2=k2^k1;
Bitset k3=get_query2(l2-),k4=get_query2(r2);
k4=k4^k3;
return (k2&k4).count();
}
IL int change(int x,int y)
{
int x1=pos[x],y1=pos[y],v1=b[x],v2=b[y];
swap(b[x],b[y]);
rep(i,x1,y1-) b1[i].set(v2,),b1[i].set(v1,);
}
#define lowbit(x) (x&(-x))
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n); read(m);
rep(i,,) ans[i]=ans[i-lowbit(i)]+;
rep(i,,n) read(a[i]);
rep(i,,n) read(b[i]);
block=sqrt(n); num=(n-)/block+;
rep(i,,num) reset(i);
rep(i,,n) pos[i]=(i-)/block+;
rep(i,,m)
{
int kk,l1,r1,l2,r2,x,y;
read(kk);
if (kk==)
{
read(l1); read(r1); read(l2); read(r2);
// wer(query(r1,r2)-query(l1-1,r2)-query(r1,l2-1)+query(l1-1,l2-1));
wer(query(l1,r1,l2,r2));
wer2();
} else
{
read(x); read(y);
if (x>y) swap(x,y);
change(x,y);
}
}
fwrite(sr,,C1+,stdout);
return ;
}
正解也很简单
把每个点对应到第二个序列
变成二维查询点数,单点修改
线段树套线段树/平衡树就可以了
然而这个东西空间很傻比
线段树套线段树不用说肯定gg了
空间比较小的线段树套平衡树
本身空间$nlogn$
然后每个里面要开$ls,rs,num,v$
然后一共插入个数是$n+4*m$的
所以计算一下就是$6e6*logn$的 可能再把ls,rs压压是可以的。。
比较简单又最快的方法是用cdq分治再套个数据结构
#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
#define ll long long
#define mep(x) memcpy(x,y,sizeof(y))
#define mid ((h+t)>>1)
namespace IO{
char ss[<<],*A=ss,*B=ss;
IL char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T>void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=(c^);
while (c=gc(),c>&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
char sr[<<],z[]; int Z,C=-;
template<class T>void wer(T x)
{
if (x<) sr[++C]='-',x=-x;
while (z[++Z]=x%+,x/=);
while (sr[++C]=z[Z],--Z);
}
IL void wer1() {sr[++C]=' ';}
IL void wer2() {sr[++C]='\n';}
template<class T>IL void maxa(T &x,T y) { if (x<y) x=y;}
template<class T>IL void mina(T &x,T y) { if (x>y) x=y;}
template<class T>IL T MAX(T x,T y) {return x>y?x:y;}
template<class T>IL T MIN(T x,T y) {return x<y?x:y;}
};
const int N=3e5;
const int M=N*;
int a[N],b[N],c[N],d[N],e[N],ans[N],n,m;
struct re{
int a,b,c,d;
}p[M],p1[M],p2[M];
#define lowbit(x) (x&(-x))
struct BIT{
int sum[N];
int query(int x)
{
int ans=;
for (int y=x;y>;y-=lowbit(y)) ans+=sum[y];
return ans;
}
void change(int x,int k)
{
for (;x<=n;x+=lowbit(x)) sum[x]+=k;
}
}B;
bool cmp(re x,re y){
return x.a<y.a;
}
void cdq_fz(int h,int t)
{
if (h==t) return;
int cnt1=,cnt2=;
rep(i,h,mid)
if (p[i].c<=) p1[++cnt1]=p[i];
rep(i,mid+,t)
if (p[i].c>=)
{
p2[++cnt2]=p[i];
}
sort(p1+,p1+cnt1+,cmp);
sort(p2+,p2+cnt2+,cmp);
int t1=;
rep(i,,cnt2)
{
while (t1<=cnt1&&p1[t1].a<=p2[i].a) B.change(p1[t1].b,p1[t1].c),t1++;
ans[p2[i].d]+=(p2[i].c-)*B.query(p2[i].b);
}
dep(i,t1-,) B.change(p1[i].b,-p1[i].c);
cdq_fz(h,mid);
cdq_fz(mid+,t);
}
bool t[N];
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
IO::read(n); IO::read(m);
rep(i,,n) IO::read(a[i]),e[a[i]]=i;
rep(i,,n) IO::read(b[i]),c[b[i]]=i;
rep(i,,n) d[i]=c[a[i]];
int num=;
rep(i,,n) p[++num]=(re){i,d[i],,i};
rep(i,,m)
{
int kk,x1,y1,x2,y2,x,y;
IO::read(kk);
if (kk==)
{
t[i]=;
IO::read(x1); IO::read(x2); IO::read(y1); IO::read(y2);
p[++num]=(re){x2,y2,,i};
p[++num]=(re){x2,y1-,,i};
p[++num]=(re){x1-,y2,,i};
p[++num]=(re){x1-,y1-,,i};
} else
{
IO::read(x); IO::read(y);
p[++num]=(re){e[b[x]],x,-,i};
p[++num]=(re){e[b[x]],y,,i};
p[++num]=(re){e[b[y]],y,-,i};
p[++num]=(re){e[b[y]],x,,i};
swap(b[x],b[y]);
}
}
cdq_fz(,num);
rep(i,,m) if (t[i]) IO::wer(ans[i]),IO::wer2();
fwrite(IO::sr,,IO::C+,stdout);
return ;
}
F:
G:
第一眼感觉很像kd-tree呀(n那么大跑啥kd-tree啊)
正解很好想
因为k只有5,所以我们对符号讨论一下维护最大最小值就好了
$nlogn*32$
CF1093的更多相关文章
- CF-1093 (2019/02/10)
CF-1093 1093A - Dice Rolling 输出x/2即可 #include<bits/stdc++.h> using namespace std; int main() { ...
- CF1093:E. Intersection of Permutations(树状数组套主席树)
题意:给定长度为N的a数组,和b数组,a和b都是1到N的排列: 有两种操作,一种是询问[L1,R1],[L2,R2]:即问a数组的[L1,R1]区间和b数组的[L2,R2]区间出现了多少个相同的数字. ...
随机推荐
- opencv + cuda编译
#获取最新代码git clone "https://github.com/opencv/opencv.git" #build目录mkdir buildcd build #使用ccm ...
- 洛谷P1066 2^k进制数(题解)(递推版)
https://www.luogu.org/problemnew/show/P1066(题目传送) (题解)https://www.luogu.org/problemnew/solution/P106 ...
- CTF--web 攻防世界web题 robots backup
攻防世界web题 robots https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=506 ...
- Ceph rdb
Ceph 独一无二地用统一的系统提供了对象.块.和文件存储功能,它可靠性高.管理简便.并且是自由软件. Ceph 的强大足以改变公司的 IT 基础架构.和管理海量数据. Ceph 可提供极大的伸缩性— ...
- Python基础和原反补码及表达式
基础语法 1.注释 “#”标注的文件 2.数字 整数,不区分long和int 进制0xa.0o10.0b10 bool,2个值True.False 浮点数 1.2.3.1314.-0.12.1.46e ...
- [Luogu P1119]灾后重建
这是一道考Floyd本质的题. 回忆一下Floyd的原理,三层循环,最外层循环枚举的是中转点,也就是用两点到中转点距离之和来更新最短路.然后来看下题目,重建时间是按照从小到大排序的,也就是说,当第i个 ...
- clickhouse的使用和技巧,仅个人
centos 安装clickhouse curl -s https://packagecloud.io/install/repositories/altinity/clickhouse/script. ...
- 文件上传(StringMVC)
我们经常会使用的一个功能是文件下载,既然有文件下载就会有文件上传,下面我们来看一下文件上传是如何实现的 首先准备好一个页面 jsp <style type="text/css" ...
- HDU-6397(2018 Multi-University Training Contest 8) Character Encoding(生成函数+组合数学)
题意 从$0$到$n-1$的数字里可重复的取至多$m$个数的和等于$k$的方案数. 思路 显然的生成函数的思路为构造 $(1+x+x^{2}+...+x^{n-1})^{m}$ 那么$x^{k}$的系 ...
- java实现多个文件以压缩包导出到本地
描述:使用java将多个文件同时压缩为压缩包,并导出到本地 /** *压缩文件并导出 */ public static void zipFiles() throws IOException { Fil ...