【弱省胡策】Round #7 Rectangle 解题报告
orz PoPoQQQ 的神题。
我的想法是:给每一个高度都维护一个 01 序列,大概就是维护一个 Map[i][j] 的矩阵,然后 Map[i][j] 表示第 i 根柱子的高度是否 ≥j。
那么怎么维护 Map[i][j] 呢。。?
首先我们把柱子按照高度从小到大排序,然后依次给每个高度建主席树,初始时 Map[i][0] 全是 1,然后如果当前高度 i 比某个柱子 j 的高度要大了,那么就单点修改 Map[i][j],然后这个就是主席树动态开节点的经典操作嘛。然后我们就相当于是要维护每一个高度的主席树,并记录其最长连续子段,记高度 i 的主席树的最长连续子段长 leni,那么最大子矩阵就是:
max{i×leni|i=1−Max_height}
然后每次单点修改只会改变一个主席树的最长连续子段,所以我们可以再弄一个堆维护这个答案。
时间空间复杂度均为 O((n+m)logh+h),可以过掉本题。
其实 h 可以扩大到 109,这样的话我们就需要离散化一下,反正有用的高度只有 O(n+m) 种。
1 #include <queue> 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 #define N 100000 + 5 8 #define M 1000000 + 5 9 #define SIZE 10000000 + 5 10 11 int n, m, Max, tot, A[N], Ord[N], Root[M]; 12 13 struct Segment_Tree 14 { 15 int l, r, Lcombo, Rcombo, combo; 16 }h[SIZE]; 17 18 struct Node 19 { 20 int id; 21 LL square; 22 Node (int _id = 0, LL _square = 0) {id = _id, square = _square;} 23 bool operator < (const Node a) const 24 { 25 return square < a.square || (square == a.square && id < a.id); 26 } 27 }; 28 29 priority_queue <Node> Q; 30 31 inline LL getint() 32 { 33 char ch = '\n'; 34 for (; ch != '-' && (ch > '9' || ch < '0'); ch = getchar()) ; 35 int f = ch == '-' ? -1 : 1; 36 LL res = ch == '-' ? 0 : ch - '0'; 37 for (ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar()) 38 res = (res << 3) + (res << 1) + ch - '0'; 39 return res * f; 40 } 41 42 inline bool cmp(int u, int v) 43 { 44 return A[u] < A[v]; 45 } 46 47 inline void Build(int &x, int l, int r) 48 { 49 x = ++ tot; 50 h[x].Lcombo = h[x].Rcombo = h[x].combo = r - l + 1; 51 if (l == r) return ; 52 int mid = l + r >> 1; 53 Build(h[x].l, l, mid); 54 Build(h[x].r, mid + 1, r); 55 } 56 57 inline void update(int x, int l, int r) 58 { 59 int mid = l + r >> 1; 60 if (h[h[x].l].Lcombo == mid - l + 1) 61 h[x].Lcombo = h[h[x].l].Lcombo + h[h[x].r].Lcombo; 62 else h[x].Lcombo = h[h[x].l].Lcombo; 63 if (h[h[x].r].Rcombo == r - mid) 64 h[x].Rcombo = h[h[x].r].Rcombo + h[h[x].l].Rcombo; 65 else h[x].Rcombo = h[h[x].r].Rcombo; 66 h[x].combo = max(max(h[h[x].l].combo, h[h[x].r].combo), h[h[x].l].Rcombo + h[h[x].r].Lcombo); 67 } 68 69 inline void Modify(int &x, int l, int r, int t) 70 { 71 h[++ tot] = h[x]; 72 x = tot; 73 if (l == r) 74 { 75 h[x].Lcombo = h[x].Rcombo = h[x].combo = 0; 76 return ; 77 } 78 int mid = l + r >> 1; 79 if (t <= mid) Modify(h[x].l, l, mid, t); 80 else Modify(h[x].r, mid + 1, r, t); 81 update(x, l, r); 82 } 83 84 int main() 85 { 86 n = getint(), m = getint(); 87 for (int i = 1; i <= n; Ord[i] = i, i ++) 88 { 89 A[i] = getint(); 90 Max = max(Max, A[i]); 91 } 92 sort(Ord + 1, Ord + n + 1, cmp); 93 Build(Root[0], 1, n); 94 for (int i = 1, t = 1; i <= Max; i ++) 95 { 96 Root[i] = Root[i - 1]; 97 for (; A[Ord[t]] == i - 1 && t <= n; t ++) 98 Modify(Root[i], 1, n, Ord[t]); 99 Q.push(Node(i, (LL) h[Root[i]].combo * i)); 100 } 101 Node x = Q.top(); 102 LL last = x.square; 103 printf("%lld\n", last); 104 while (m --) 105 { 106 int pos = (int) (getint() ^ last); 107 Modify(Root[A[pos]], 1, n, pos); 108 Q.push(Node(A[pos], (LL) h[Root[A[pos]]].combo * A[pos])); 109 A[pos] --; 110 Node x; 111 for (x = Q.top(); (LL) x.id * h[Root[x.id]].combo != x.square; Q.pop(), x = Q.top()) ; 112 last = x.square; 113 printf("%lld\n", last); 114 } 115 116 return 0; 117 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理