当前位置: 首页 > news >正文

题解:P8930 「TERRA-OI R1」神,不惧死亡

P8930 「TERRA-OI R1」神,不惧死亡

大水紫

首先发现是神秘区间问题,考虑支持区间操作的数据结构。

发现数据范围是 \(1e5\) ,而且维护的东西很神秘,直接考虑分块或莫队。

如果你不了解分块

将题意转化为寻找在区间 \([l,r]\) 中,值处于 \([a,b]\) 中第一个出现次数为偶数的点(设为 \(x\))的后继(第一个比它大的数)。

这很好理解,因为处于 \(x\) 之前的数肯定是出现过奇数次或者没出现。

我们将 \(x\) 进行操作至其全部删除,则比他小的数的出现次数减一,也即奇数次变成偶数次。

然后继续这个过程。

这样就能把小于等于 \(x\) 的数全部删除,则最小值即为 \(x\) 的后继(第一个比 \(x\) 大的数)。

显然先删除比 \(x\) 小的数一定没有直接删 \(x\) 优。

如果删除比 \(x\) 大的数,则在删到 \(x\) 的时候会有两种情况:

  • 一种是 \(x\) 是奇数个,则无法删除 \(x\),最小值即为 \(x\),劣于 \(x\) 的后继。

  • 一种是 \(x\) 是偶数个,则因为比 \(x\) 小的数的奇偶性与其不同,则会造成无法删除比其小的数,最小值小于 \(x\),劣于 \(x\) 的后继。

因此得证,可以如此转化题意。

因为是与值域有关,所以考虑值域分块。

我们要维护两个查询,一个是查询第一个出现偶数次的值,另一个是每个值的后继。

我们依然采用传统的散块暴力查。

对于每个整块,维护两个数组,一个存该块内出现偶数次的数的个数,一个维护块内出现不同的的数的个数。

然后对于区间操作,直接上莫队即可。

时间复杂度 \(O(n ^ \frac{5}{3})\)

可以通过此题(顺便拿到了次优解)。

另外提一嘴,貌似可以在线做,直接对区间分块,维护每个数的出现次数前缀和,然后上一棵树状数组维护加减操作。时间复杂度 \(O(m \sqrt[3]{\frac{n^2}{m}log^2{n}})\),大概是 \(O(n \sqrt{n})\),乱胡的,不对别打我 qwq。

标程

#include<bits/stdc++.h>
#define int long long 
#define con putchar_unlocked(' ')
#define ent putchar_unlocked('\n')
#define Blue_Archive return 0
using namespace std;
constexpr int N = 1e5 + 3;
constexpr int M = 320;
constexpr int mid = 6e4 + 7;
constexpr int INF = INT32_MAX;
constexpr char me[] = "終末なにしてますか?忙しいですか?救ってもらっていいですか?";int n;
int m;
int len1;
int len2;
int cntq;
int cntc;
int a[N];
int st[M];
int ed[M];
int id1[N];
int id2[N];
int cnt[N];
int ans[N];
int cntk[M]; // 每个块存在偶数的个数
int totk[M]; // 每个块存在的数的个数struct miku
{int l,r,a,b;int id,tim;
}q[N];struct mika
{int pos;int val;
}chg[N];inline int read()
{int k = 0,f = 1;char c = getchar_unlocked();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar_unlocked();}while(c >= '0' && c <= '9') k = (k << 3) + (k << 1) + c - '0',c = getchar_unlocked();return k * f;
}inline void write(int x)
{if(x < 0) putchar_unlocked('-'),x = -x;if(x > 9) write(x / 10);putchar_unlocked(x % 10 + '0');
}inline void add(int x)
{if(!cnt[x]) totk[id2[x]] ++;cnt[x] ++;if(cnt[x] && cnt[x] % 2 == 0) cntk[id2[x]] ++;
}inline void del(int x)
{if(cnt[x] && cnt[x] % 2 == 0) cntk[id2[x]] --;cnt[x] --;if(!cnt[x]) totk[id2[x]] --;
}inline int query_nxt(int val,int r) // 查找后继
{if(id2[val] == id2[r]){for(int i = val + 1;i <= r;i ++) if(cnt[i]) return i;return -1;}for(int i = val + 1;i <= ed[id2[val]];i ++) if(cnt[i]) return i;for(int i = id2[val] + 1;i < id2[r];i ++){if(!totk[i]) continue;for(int j = st[i];j <= ed[i];j ++) if(cnt[j]) return j;}for(int i = st[id2[r]];i <= r;i ++) if(cnt[i]) return i;return -1;
}inline int query(int l,int r) // 查找第一个为偶数的数
{if(id2[l] == id2[r]){for(int i = l;i <= r;i ++){if(cnt[i] && cnt[i] % 2 == 0) return query_nxt(i,r);}return -1;}for(int i = l;i <= ed[id2[l]];i ++) if(cnt[i] && cnt[i] % 2 == 0) return query_nxt(i,r);for(int i = id2[l] + 1;i < id2[r];i ++){if(!cntk[i]) continue;for(int j = st[i];j <= ed[i];j ++){if(cnt[j] && cnt[j] % 2 == 0) return query_nxt(j,r);}} for(int i = st[id2[r]];i <= r;i ++) if(cnt[i] && cnt[i] % 2 == 0) return query_nxt(i,r);return -1;
}signed main()
{// freopen("data.in","r",stdin);freopen("data.out","w",stdout);n = read();m = read();len1 = pow(n,0.667);for(int i = 1;i <= n;i ++) {a[i] = read();id1[i] = (i - 1) / len1 + 1;}len2 = sqrt(n);for(int i = 1;i <= n;i ++){id2[i] = (i - 1) / len2 + 1;if(!st[id2[i]]) st[id2[i]] = i;ed[id2[i]] = i;}cntc = 1;for(int i = 1,op;i <= m;i ++){op = read();if(op == 1){chg[++ cntc].pos = read();chg[cntc].val = read();}if(op == 2){q[++ cntq].l = read();q[cntq].r = read();q[cntq].a = read();q[cntq].b = read();q[cntq].tim = cntc;q[cntq].id = cntq;}}sort(q + 1,q + cntq + 1,[](miku a,miku b){return id1[a.l] == id1[b.l] ? id1[a.r] == id1[b.r] ? a.tim < b.tim : a.r < b.r : a.l < b.l;});for(int i = 1,l = 1,r = 0,t = 1;i <= cntq;i ++){while(l < q[i].l) del(a[l ++]);while(l > q[i].l) add(a[-- l]);while(r < q[i].r) add(a[++ r]);while(r > q[i].r) del(a[r --]);while(t > q[i].tim){if(chg[t].pos >= l && chg[t].pos <= r) del(a[chg[t].pos]);a[chg[t].pos] -= chg[t].val;if(chg[t].pos >= l && chg[t].pos <= r) add(a[chg[t].pos]);t --;}while(t < q[i].tim){t ++;if(chg[t].pos >= l && chg[t].pos <= r) del(a[chg[t].pos]);a[chg[t].pos] += chg[t].val;if(chg[t].pos >= l && chg[t].pos <= r) add(a[chg[t].pos]);}ans[q[i].id] = query(q[i].a,q[i].b);}for(int i = 1;i <= cntq;i ++) write(ans[i]),ent;Blue_Archive;
}

后记

抄题解是不好的行为哟~

http://www.hskmm.com/?act=detail&tid=38279

相关文章:

  • 2025 OSCAR丨与创新者同频!Apache RocketMQ 邀您共赴开源之约
  • 生产环节最容易出问题的三个点,老板必须盯紧
  • 2025年PSA制氮设备厂家权威推荐榜单:电解水制氢设备/氦气纯化系统/氘气回收纯化源头厂家精选
  • 解决git clone只有master分支的问题
  • 一文读懂循环神经网络(RNN):原理、局限与LSTM解决方案 - 指南
  • 2025年搬家纸箱权威推荐榜单:物流包装/电商纸箱/平口纸箱源头厂家精选
  • 大数据案例 -2025/10/24
  • 2025年阳台壁挂太阳能厂家权威推荐榜单:分体式阳台太阳能/阳台壁挂太阳能热水器/分体式阳台太阳能源头厂家精选
  • 使用C# 控制ethercat从站设备
  • 从价值直觉到价值理性:AI元人文演进路径解读
  • 0269-GRPC-使用 prost 编码
  • 0268-GRPC-prost 生成文件到目录
  • 0271-GRPC-prost 带长度的编解码
  • 2025 年坡口机源头厂家最新推荐排行榜:欧盟 CE 认证企业领衔,含 15 年工业服务经验品牌,自走式/自动/板材/管道坡口机厂家推荐
  • 0270-GRPC-使用 prost 解码
  • 完整教程:Java开发者进阶之路
  • 动手动脑4
  • python+request+unittest自动化测试
  • 2025 年保温涂料厂家最新推荐排行榜:聚焦技术专利与管理体系认证的优质品牌耐高温/防火耐热/防腐/纳米介孔微珠中空粒子保温涂料公司推荐
  • 2025年云南独立成团游公司权威推荐榜单:云南旅游团/云南私享之旅/云南专属行程游源头公司精选
  • 2025 年气凝胶生产厂家最新推荐排行榜:含气凝胶毡 / 粉 / 隔热板 / 保温罩 / 陶瓷板品牌,优质厂家推荐
  • 102302143郑泽雄第一次作业
  • 作业4
  • 2025年5.5KW工业吸尘器厂家权威推荐榜单:380V防爆吸尘器/7.5KW工业吸尘器/水浴式吸尘器源头厂家精选
  • 2025 年兰州凯文中学推荐:兰州凯文中学,二十载深耕民办教育 双师赋能全维育人 以低进高出成效书写成长答卷
  • OpenEuler 22.03 手动升级 OpenSSH 至 10.2p1 完整方案
  • 配置GOPRIVATE引用私有仓库
  • 【C++】函数参数传递
  • 2025年3d全息投影生产厂家权威推荐榜单:全息投影展厅/全息投影沙盘/全息投影源头厂家精选
  • 用AI“抄底”双十一