CF1093E 题解
来一发 \(O(n \sqrt n)\) 时间,\(O(n)\) 空间的分块写法。
首先建模,把 数值 \(x\) 在两个数组中出现的位置作为坐标,问题就转化为一个二维动态数点。
考虑用序列分块维护第一维,第二维用 值域分块 维护,这样子平衡复杂度玩就得到一个 \(O(n \sqrt n)\) 时间的做法,但是空间很大。
考虑到块与块之间并无联系,所以考虑 逐块处理 也就是说把每个块的修改与贡献离线下来分开计算,那么空间就被优化到了 \(O(n)\)。
综上,我们就可以写出代码了。
#include<bits/stdc++.h>
#define int long long
//#define lowbit(x) (x&-(x))
using namespace std;
const int maxn = 6e5+114;
const int maxsq = 500;
const int warma = 447;
int n,cnt;
struct Node{
int opt,x,l,r,L,R;
}Q[maxn];
int anser[maxn];
pair<int,int> wyb[maxn],zbz[maxn];//处理时的数组 & 原本的数组
int val(int l1,int r1,int l2,int r2){//计算两个区间的交集大小
int mxl=max(l1,l2),mir=min(r1,r2);
if(mxl>mir) return 0;
else return (mir-mxl+1);
}
class block{//O(\sqrt n) 区间修改 O(1) 区间查询
private:
int bl_pre[maxsq][maxsq];//块内前缀和
int tag[maxsq];//块内标记
int pre[maxsq];//块间前缀和
public:
void add(int l,int r,int v);
int query(int l,int r);
void init();
}chifan;
void block::init(){
for(int i=0;i<maxsq;i++)
for(int j=0;j<maxsq;j++)
bl_pre[i][j]=tag[i]=pre[i]=0;
}
void block::add(int l,int r,int v){
int bl=l/warma;
int lpos=l%warma;
if(lpos==0){
lpos=warma;
bl--;
}
int br=r/warma;
int rpos=r%warma;
if(rpos==0){
rpos=warma;
br--;
}
//整块处理
if(bl==br){
for(int i=lpos;i<=rpos;i++){
bl_pre[bl][i]+=v*(i-lpos+1);
}
for(int i=rpos+1;i<=warma;i++){
bl_pre[bl][i]+=v*(rpos-lpos+1);
}
pre[0]=bl_pre[0][warma];
for(int i=1;i<=warma;i++){
pre[i]=pre[i-1]+bl_pre[i][warma]+tag[i]*warma;
}
return ;
}
for(int i=bl+1;i<=br-1;i++){
tag[i]+=v;
}
//头部残块处理
for(int i=lpos;i<=warma;i++){
bl_pre[bl][i]+=v*(i-lpos+1);
}
//尾部残块处理
for(int i=1;i<=rpos;i++){
bl_pre[br][i]+=v*i;
}
for(int i=rpos+1;i<=warma;i++){
bl_pre[br][i]+=v*rpos;
}
//块间处理
pre[0]=bl_pre[0][warma];
for(int i=1;i<=warma;i++){
pre[i]=pre[i-1]+bl_pre[i][warma]+tag[i]*warma;
}
return ;
}
int block::query(int l,int r){
int bl=l/warma;
int lpos=l%warma;
if(lpos==0){
lpos=warma;
bl--;
}
int br=r/warma;
int rpos=r%warma;
if(rpos==0){
rpos=warma;
br--;
}
if(bl==br){
return bl_pre[bl][rpos]-bl_pre[bl][lpos-1]+tag[bl]*(rpos-lpos+1);
}
int res=0;
res+=pre[br-1]-pre[bl];
res+=bl_pre[bl][warma]-bl_pre[bl][lpos-1]+(warma-lpos+1)*tag[bl];
res+=bl_pre[br][rpos]+tag[br]*rpos;
return res;
}
void work(int lt,int rt){//逐块处理
rt=min(rt,n);
chifan.init();
for(int i=1;i<=n;i++) wyb[i]=zbz[i];
for(int i=lt;i<=rt;i++){
chifan.add(wyb[i].first,wyb[i].second,1);
}
for(int i=1;i<=cnt;i++){
if(Q[i].opt==1){
int l=Q[i].l,r=Q[i].r,L=Q[i].L,R=Q[i].R;
if(l<=lt&&rt<=r){//被包含
anser[i]+=chifan.query(L,R);
}
else if(lt<=l&&r<=rt){//另外一种被包含
int res=0;
for(int i=l;i<=r;i++){
res+=val(wyb[i].first,wyb[i].second,L,R);
}
anser[i]+=res;
}
else if(rt>=r&&r>=lt){
int res=0;
for(int i=lt;i<=r;i++){
res+=val(wyb[i].first,wyb[i].second,L,R);
}
anser[i]+=res;
}
else if(lt<=l&&l<=rt){
int res=0;
for(int i=l;i<=rt;i++){
res+=val(wyb[i].first,wyb[i].second,L,R);
}
anser[i]+=res;
}
}
else{
int x=Q[i].x,l=Q[i].l,r=Q[i].r;
if(lt<=x&&x<=rt){
chifan.add(wyb[x].first,wyb[x].second,-1);
wyb[x].first=l,wyb[x].second=r;
chifan.add(wyb[x].first,wyb[x].second,1);
}
}
}
}
int sq;
int q;
int a[maxn],b[maxn];
int A[maxn],B[maxn];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
sq=sqrt(n);
for(int i=1;i<=n;i++){
cin>>a[i];
A[a[i]]=i;
}
for(int i=1;i<=n;i++){
cin>>b[i];
B[b[i]]=i;
}
for(int i=1;i<=n;i++){
zbz[A[i]].first=B[i];
zbz[A[i]].second=B[i];
}
for(int i=1;i<=q;i++){
int OPT;
cin>>OPT;
if(OPT==1){
int la,ra,lb,rb;
cin>>la>>ra>>lb>>rb;
cnt++;
Q[cnt].opt=1;
Q[cnt].l=la;
Q[cnt].r=ra;
Q[cnt].L=lb;
Q[cnt].R=rb;
}
else{
int x,y;
cin>>x>>y;
//b[x] - A[b[x]] x -> A[b[x]] y
//b[y] - A[b[y]] y -> A[b[y]] x
//b[x] - b[y]
//B[b[x]]
cnt++;
Q[cnt].opt=2;
Q[cnt].x=A[b[x]];
Q[cnt].l=y;
Q[cnt].r=y;
cnt++;
Q[cnt].opt=2;
Q[cnt].x=A[b[y]];
Q[cnt].l=x;
Q[cnt].r=x;
swap(b[x],b[y]);
swap(B[b[x]],B[b[y]]);
}
}
int L=1,R=sq;
while(L<=n){
work(L,R);
L+=sq,R+=sq;
}
for(int i=1;i<=cnt;i++){
if(Q[i].opt==1) cout<<anser[i]<<'\n';
}
}
/*
6 2
5 1 4 2 3 6
2 5 3 1 4 6
2 2 4
1 2 3 3 5
*/
题外话:这一道题我口胡过一个线段加和一个二维数最大值的加强版(而且写出来了,这题代码就是这么改出来的)。
CF1093E 题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- String.split()遇到空字符串不解析的情况
1.split的api说明 stringObj.split([separator,[limit]]) stringObj:要被分解的 String separator:字符串或正则表达式对象 limi ...
- Nokia 5GC 产品概览
目录 文章目录 目录 Nokia SR OS Nokia NSP NFM-P Nokia 7750 SR-MG 5G User Plane Forwarding Mobile Gateway Non- ...
- EDP .Net开发框架--权限
平台下载地址:https://gitee.com/alwaysinsist/edp 权限介绍 权限实际上就是谁有权使用或是访问什么,这里的"谁"可以视作"授权对象&quo ...
- golang select 和外层的 for 搭配
select语句通常与for循环搭配使用,但并不是必须的. 在某些情况下,select可能会直接放在一个独立的goroutine中,没有外层的for循环. 这通常发生在你知道只会有一次或有限次操作的情 ...
- PyQGIS二次开发指南
当你的数据处理使用的是Python语言,而你的导师又让你开发界面,那么PyQGIS二次开发指南是你必读的圣经.QGIS支持Python语言进行二次开发,你将学会如何使用Qt Designer进行界面设 ...
- P1036 [NOIP2002 普及组] 选数
传送锚点:https://www.luogu.com.cn/problem/P1036 题目描述 已知 \(n\) 个整数 \(x_1,x_2,\cdots,x_n\),以及 \(1\) 个整数 \( ...
- block专递参数导致野指针引发crash
一.问题引入 近日开发中引入一个随机crash,Crash堆栈如下: Exception Type: SIGSEGV Exception Codes: SEGV_ACCERR at 0x0000000 ...
- 【Effective C++】设计与声明——考虑写出一个不抛异常的swap函数
wap是个有趣的函数.原本它只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来实现自我赋值可能性的一个常见机制.所谓swap两对象值,就是将两对象的值交换. 典型实现 缺省情况下的swap动作 ...
- 开源一站式敏捷测试管理平台 itest(爱测试) 6.6.1 发布,安全升级及新增强
(一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试5合1,又有丰富的统计分析.可按测试包分配测试用例执行 ...
- sort awk 文本处理命令
sort: 1.将文件的每一行作为一个单位,相互比较 2.默认升序 3.以字符来进行对比,从首字符开始往后,依次按ASCII码值排序 sort 显示文件内容 (类似cat) 选项: -u 去掉重复行 ...