P6578 魔法少女网站

给定一个长为 nnn 的序列,定义区间 [l,r][l,r][l,r] 的子区间为所有形如 [l′,r′][l',r'][l′,r′] 的区间,满足 l′,r′l',r'l′,r′ 为整数,且 l≤l′≤r′≤rl \le l' \le r' \le rl≤l′≤r′≤r。

有 mmm 次操作:

  • 1 x y:将 xxx 位置的值修改为 yyy。
  • 2 l r x:查询区间 [l,r][l,r][l,r] 中有多少子区间的最大值小于或等于 xxx。

1≤n,m≤3×1051 \leq n,m\leq 3\times 10^51≤n,m≤3×105,时限 3.50s3.50\text{s}3.50s,空限 64MB64\text{MB}64MB。

sol

第十分块。

难度评分:666。

对于查询,考虑贡献,容易发现,设 b[i]=(a[i]≤x)b[i]=(a[i] \leq x)b[i]=(a[i]≤x),那么我们现在的问题就是询问区间内 bbb 的所有为 111 的极长子区间的 siz×(siz+1)2\frac{siz \times(siz+1)}{2}2siz×(siz+1)​ 之和。

再考虑怎么维护这个极长子区间。

由于 xxx 随时会变,相当于就是我们每次会修改一些点 0→10 \to 10→1 或者 1→01 \to 01→0。

对于 0→10 \to 10→1 这种情况,我们考虑把询问按 xxx 升序排序,然后我们发现这个满足的数会越来越多,然后分类讨论几种情况:

  • 单独一个区间,直接加。
  • 在一个区间的左边,直接加。
  • 在一个区间的右边,直接加。
  • 连接两个区间,修改区间信息后直接加。

但是对于 1→01 \to 01→0 这种情况,即修改时可能会出现的情况,每一次都需要考虑,复杂度显然错误。

类似于回滚莫队的思想,将一个东西变成没有删除的。

容易发现 1→01 \to 01→0 这种情况只会在这 mmm 个操作中出现,先将有修改的位置空出来,然后每一次询问时再将这些位置插入进去,记录一下改变的答案和指针个数,询问完了撤回即可,这样的话这些操作全部变成了将 000 换成 000 或 111,就可以维护了。

但是我们发现,这些有修改的位置最多有 mmm 个,每次询问都要修改,那么总时间复杂度是 O(m2)\mathcal O(m^2)O(m2) 的,直接爆炸。

考虑操作分块:每 m\sqrt{m}m​ 次重建原序列,然后暂时储存的 m\sqrt{m}m​ 次操作一起做。

这样这些有修改的位置最多有 m\sqrt{m}m​ 个,每次询问都要修改,那么单个操作块的时间复杂度是 O(m×m)=O(m)\mathcal O(\sqrt{m} \times \sqrt m)=\mathcal O(m)O(m​×m​)=O(m) 的,总时间复杂度是 O(mn\mathcal O(m \sqrt{n}O(mn​ 的,可过。

查询时,散块记录,整块逐块扫过去即可。

所以总时间复杂度为 O(nn)\mathcal O(n \sqrt n)O(nn​),总空间复杂度为 O(n)\mathcal O(n)O(n)。

总结:序列分块加操作分块再加大力卡常。

01-29 17:25:11 / 1.23min / 22.48MB / 5.82KB C++98 O2\text{01-29 17:25:11 / 1.23min / 22.48MB / 5.82KB C++98 O2}01-29 17:25:11 / 1.23min / 22.48MB / 5.82KB C++98 O2。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>#define re registernamespace Fread
{const int SIZE = 1 << 23;char buf[SIZE], *S, *T;inline char getchar(){if (S == T){T = (S = buf) + fread(buf, 1, SIZE, stdin);if (S == T)return '\n';}return *S++;}
}
namespace Fwrite
{const int SIZE = 1 << 23;char buf[SIZE], *S = buf, *T = buf + SIZE;inline void flush(){fwrite(buf, 1, S - buf, stdout);S = buf;}inline void putchar(char c){*S++ = c;if (S == T)flush();}struct NTR{~NTR(){flush();}} ztr;
}#ifdef ONLINE_JUDGE
#define getchar Fread::getchar
#define putchar Fwrite::putchar
#endifinline int read()
{re int x = 0, f = 1;re char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + (c ^ 48);c = getchar();}return x * f;
}inline void write(re long long x)
{if(x > 9)write(x / 10);putchar(x % 10 + 48);
}inline int min(re const int &x, re const int &y)
{return x < y ? x : y;
}const int N = 3e5 + 1, S = 2e3 + 1;struct Modify
{int opt, pos, val;
} q1[S];struct Query
{int opt, l, r, x, id;
} q2[S];int n, m, c1, c2, a[N];long long calc[N];bool seq[N];int L[S], R[S], id[N], p[N], sum[S];inline void clear()
{memset(seq, 0, sizeof seq);memset(p, 0, sizeof p);memset(sum, 0, sizeof sum);
}inline void init()
{re int sqn = sqrt(n * 4 / 5 + 1);for(re int i = 1, j, c = 1; i <= n; i = j + 1, ++c){L[c] = i, R[c] = j = min(n, i + sqn);for(re int t = L[c]; t <= R[c]; ++t)id[t] = c;}
}int top;struct Node
{int id, ans, t1[4];bool flg;inline void clear(){t1[0] = t1[1] = t1[2] = t1[3] = flg = 0;}
} sta[S], tmp;inline void modify(re const int &pos, re bool flg)
{p[pos] = pos, seq[pos] = 1, tmp.id = pos;re const int lst = pos - 1, nxt = pos + 1, tmp_p = p[lst];re const bool flg1 = (seq[lst] && L[id[pos]] != pos), flg2 = (seq[nxt] && R[id[pos]] != pos);if(!flg1 && !flg2)tmp.clear(), tmp.ans = 1;else{tmp.flg = 1;if(flg1 && flg2){tmp.ans = (nxt - p[lst]) * (p[nxt] - lst);tmp.t1[0] = p[lst], tmp.t1[1] = p[p[lst]], p[p[lst]] = p[nxt];tmp.t1[2] = p[nxt], tmp.t1[3] = p[p[nxt]], p[p[nxt]] = tmp_p;}else{if(flg1){tmp.ans = nxt - p[lst];tmp.t1[0] = pos, tmp.t1[1] = p[pos], p[pos] = p[lst];tmp.t1[2] = p[lst], tmp.t1[3] = p[p[lst]], p[p[lst]] = pos;}else{tmp.ans = p[nxt] - lst;tmp.t1[0] = pos, tmp.t1[1] = p[pos], p[pos] = p[nxt];tmp.t1[2] = p[nxt], tmp.t1[3] = p[p[nxt]], p[p[nxt]] = pos;}}}sum[id[pos]] += tmp.ans;if(flg) sta[++top] = tmp;
}inline void back()
{while(top){tmp = sta[top--], sum[id[tmp.id]] -= tmp.ans, seq[tmp.id] = 0;if(tmp.flg){p[tmp.t1[2]] = tmp.t1[3];p[tmp.t1[0]] = tmp.t1[1];}}
}inline long long query(const int &l, const int &r)
{re long long ans = 0;if(id[l] == id[r]){int cnt = 0;for(re int i = l; i <= r; ++i)if(seq[i])cnt++;elseans += calc[cnt], cnt = 0;return ans + calc[cnt];}re int c1 = 0, c2 = 0;for(re int i = l; i <= R[id[l]]; ++i)if(seq[i])c1++;elseans += calc[c1], c1 = 0;for(re int i = r; i >= L[id[r]]; --i)if(seq[i])c2++;elseans += calc[c2], c2 = 0;re int tot = c1;for(re int i = id[l] + 1; i <= id[r] - 1; ++i)if(p[L[i]] == R[i])tot += R[i] - L[i] + 1;else{if(seq[L[i]]){tot += p[L[i]] - L[i] + 1, ans -= calc[p[L[i]] - L[i] + 1];}ans += calc[tot] + sum[i], tot = 0;if(seq[R[i]]){tot += R[i] - p[R[i]] + 1, ans -= calc[R[i] - p[R[i]] + 1];}}return ans + calc[tot + c2];
}long long ans[S];int cnt, head[N];struct Edge
{int to, nxt;
} G[N];bool broke[N], use[N];inline void add(const int &u, const int &v)
{G[++cnt] = {v, head[u]};head[u] = cnt;
}inline bool cmp(const Query &x, const Query &y)
{return x.x < y.x;
}inline void solve()
{clear();for(re int i = 1; i <= c1; ++i)broke[q1[i].pos] = 1;for(re int i = 1; i <= n; ++i)if(!broke[i])add(a[i], i);std::sort(q2 + 1, q2 + c2 + 1, cmp);int pot = 1;for(re int i = 1; i <= c2; ++i){while(pot <= q2[i].x){for(re int i = head[pot]; i; i = G[i].nxt)modify(G[i].to, 0);pot++;}for(re int j = c1; j >= 1; --j)if(q1[j].opt < q2[i].opt && !use[q1[j].pos]){use[q1[j].pos] = 1;if(q1[j].val <= q2[i].x)modify(q1[j].pos, 1);}for(re int j = 1; j <= c1; ++j)if(!use[q1[j].pos]){use[q1[j].pos] = 1;if(a[q1[j].pos] <= q2[i].x)modify(q1[j].pos, 1);}ans[q2[i].id] = query(q2[i].l, q2[i].r);back();for(re int j = 1; j <= c1; ++j)use[q1[j].pos] = 0;}cnt = 0;memset(head, 0, sizeof head);for(re int i = 1; i <= c1; ++i)broke[q1[i].pos] = 0;
}signed main()
{n = read(), m = read();int sqm = sqrt(m * 11);init();for(re int i = 1; i <= n; ++i)a[i] = read();for(re int i = 1; i <= n; ++i)calc[i] = 1ll * i * (i + 1) / 2;for(re int i = 1, j; i <= m; i = j + 1){j = min(m, i + sqm), c1 = c2 = 0;for(re int t = i; t <= j; ++t)if(read() == 1)q1[++c1] = {t, read(), read()};elseq2[++c2] = {t, read(), read(), read(), c2};solve();for(re int t = 1; t <= c2;++t)write(ans[t]), putchar('\n');for(re int t = 1; t <= c1; ++t)a[q1[t].pos] = q1[t].val;}
}

P6578 魔法少女网站相关推荐

  1. [Ynoi2019]魔法少女网站

    魔法少女网站 题解 魔鬼卡常题,我卡了一周的常 由于我们查询的是最大值不大于xxx的区间个数,我们可以考虑将原序列转换成0/10/10/1序列,小于等于xxx的位置为111,大于xxx的位置为000, ...

  2. 【bzoj4399】魔法少女LJJ 并查集+权值线段树合并

    题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道"这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉 ...

  3. bzoj4399 魔法少女LJJ

    这题不愧为4399. 4399: 魔法少女LJJ Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 622  Solved: 145 [Submit][ ...

  4. BZOJ 4399: 魔法少女LJJ

    4399: 魔法少女LJJ Time Limit: 20 Sec Memory Limit: 162 MB Submit: 287 Solved: 73 Description 在森林中见过会动的树, ...

  5. bzoj 4399 魔法少女LJJ

    4399: 魔法少女LJJ Time Limit: 20 Sec  Memory Limit: 162 MB http://www.lydsy.com/JudgeOnline/problem.php? ...

  6. 魔法少女 LJJ——线段树

    题目 [题目描述] 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女 LJJ 已经觉得自己见过世界上的所有稀奇古怪的事情了. LJJ 感叹道"这里真是个迷人的绿色世界,空气清新. ...

  7. 【BZOJ 4399】魔法少女LJJ

    [题目] 传送门 题目描述: 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女 LJJ 已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ 感叹道"""这里 ...

  8. BZOJ 4399: 魔法少女LJJ 线段树合并 + 对数

    Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道"这里真是个迷人的绿色世界,空气清新.淡雅 ...

  9. BZOJ4399魔法少女LJJ——线段树合并+并查集

    题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道"这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉 ...

最新文章

  1. Android之一窥究竟Activity间的数据传递以及Intent的用处
  2. 【HNOI2007】紧急疏散
  3. boost::geometry::detail::overlay::select_rings用法的测试程序
  4. u盘启动 联想一体机_联想Y430pAT-ISE(H)U盘安装Win7系统教程
  5. 我的JavaScript for Visual Studio插件开源了
  6. python中的文件数据保存
  7. 清华2020计算机系张晨,2020清华特奖入围名单公布:电子系学霸两篇顶会一作
  8. 手把手教你使用Python+scrapy爬取山东各城市天气预报
  9. WPF之DataTemplate(转)
  10. 分布式爬虫搭建系列 之二-----神器PyCharm的安装
  11. 天弘基金:中国的BlackRock?
  12. FME官方软件快速下载
  13. 手机1像素线粗_移动端1像素边框问题
  14. 动画设计基础(三点一节)-3d max2014 裙摆(飘带插件)
  15. 纯前端提示页面版本更新
  16. 一文读懂keepalive的工作原理
  17. 如何去除图片雾化?给你推荐图片去雾怎么去除的方法
  18. ftp服务器匿名用户文件夹,ftp服务器匿名用户文件夹
  19. CI130X智能语音芯片应用于空气炸锅,可实现离线语音控制空气炸锅,高抗噪高识别率
  20. 文本编辑器(1.0)

热门文章

  1. 几行代码解决京东购物界面
  2. 海康威视主码流和子码流的区别
  3. 初中计算机课师徒结对活动记录,师徒结对活动记录表10张(师傅尚积东徒弟丁明路)(备课6节听课4节).doc...
  4. Σoφoς:简单但有效的前向安全对称可搜索加密
  5. SpringBoot+Vue项目社团网站
  6. 炒菜机器人放食材的顺序_机器人能否消灭厨师这个职业?
  7. 【002】SPARC V8 体系结构第一章介绍
  8. NLP:MRC常用数据集
  9. 机器人编程要学哪些知识
  10. 外貌测试软件准确吗,相貌测试(史上最准的颜值测试)