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 ...
随机推荐
- 利用神经网络对脑电图(EEG)降噪------开源的、低成本、低功耗微处理器神经网络模型解决方案
具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 这个示例展示了如何使用EEGdenoiseNet基准数据集[1]和深度学习回归去除脑电图(EEG ...
- 在jeecg-boot中密码的使用
1.生成密码并入库保存 String id= SnowflakeIdUtil.nextValue();//生成id operatCompany.setId(id); String salt = oCo ...
- CSRF(Pikachu靶场练习)
CSRF(get) 自己随便输点东西,回显登录失败,查看源码没发现什么 点开提示,登录进去看看 看到可以修改个人信息,我们把居住改成China,修改成功,没发现urlhttp://127.0.0.1/ ...
- java学习之旅(day.22)
CSS 前端三要素:HTML.CSS.javaScript 结构 表现 交互 相当于骨头,表皮 ,血肉吧 如何学习CSS CSS是什么 CSS怎么用(快速入门) CSS选择器(重点+难点) 美化网 ...
- 基于Python实现MapReduce
一.什么是MapReduce 首先,将这个单词分解为Map.Reduce. Map阶段:在这个阶段,输入数据集被分割成小块,并由多个Map任务处理.每个Map任务将输入数据映射为一系列(key, va ...
- Django测试与持续集成:从入门到精通
title: Django测试与持续集成:从入门到精通 date: 2024/5/18 16:38:41 updated: 2024/5/18 16:38:41 categories: 后端开发 ta ...
- iOS技术管理思路
iOS技术管理思路
- 006. Gitlab组件介绍
Gitlab组件 [root@master tools]# gitlab-ctl status #检查服务状态 run: gitaly: (pid 26704) 2201s; run: log: (p ...
- k8s——daemonset
daemonset 为每一个匹配的node都部署一个守护进程 # daemonset node:type=logs daemonset 选择节点 - nadeSelector: 只调度到匹配指定的la ...
- python-判断两个序列的成员是否一样
目的:判断两个序列的成员是否一样,如:list1 = [1, 2],list2 = [2, 1],则两个序列的成员是一样的. 实现:借助集合set()的性质实现. 代码如下: 1 if __name_ ...