扫描线模板
1.并查集模板2.求质因数模板3.二分图最大匹配模板(匈牙利算法)4.欧拉函数模板5.ST表模板6.快速幂模板7.字典树模板8.矩阵模板9.Dijkstra单源最短路模板10.最近公共祖先模板(LCA)11.拓扑排序模板12.区间素数筛模板13.Kruskal和Prim模板14.树状数组模板15.二维坐标离散化模板16.单点修改区间查最值-树状数组模板17.KMP模板18.二叉搜索树模板19.DIjkstra进阶模板 路径记录 按权重(结点数最小等)记录20.判断负环模板21.Exgcd 模板22.压位高精度模板23.线段树模板
24.扫描线模板
25.莫队模板26.带修莫队模板27.SCC缩点模板28.取模+组合数29.FFT 高精度乘法模板30.字符串自然溢出哈希/单哈希/双哈希模板31.树模板32.dsu on tree 模板33.线段树模板重制34.主席树模板35.大数质因数分解模板36.线段树合并模板37.int128输入输出流38.Meissel_Lehmer模板39.浮点高精度40.自适应辛普森法41.unordered_map随机底数种子#include<bits/stdc++.h> using namespace std; using i64 = long long; const int N = 1e6 + 5; //本模板是从左往右扫的,从下往上扫同理 #define ls (rt<<1) #define rs (rt<<1|1) i64 cover[N * 8]; //存放i节点对应区间覆盖情况的值 i64 n; i64 len[N * 8]; i64 yy[N * 2]; //存放离散后的y值,下标用lowerbound进行查找 i64 cnt = 0; struct node { i64 x; i64 up, down;; //边的y坐标上,y坐标下 i64 inout;//入边为1,出边为-1 } line[N * 2], u; bool cmp(node a, node b) { if ( a.x == b.x ) return a.inout > b.inout; //一定是加边在前面!!! return a.x < b.x; } void pushup( i64 l, i64 r, i64 rt ) { //pushup其实主要就思考在什么情况,需要更新哪些信息来维护线段树 if ( cover[rt] > 0 ) len[rt] = yy[r] - yy[l]; //如果某个节点的cover为正,那么这个点对应区间的长度全为有效的 else if ( l + 1 == r ) len[rt] = 0; //到了叶子节点 else len[rt] = len[ls] + len[rs]; } void update( i64 yl, i64 yr, i64 pd, i64 l, i64 r, i64 rt ) { if ( yl > r || yr < l ) return ; if ( yl <= l && yr >= r ) { cover[rt] += pd;//根据出边入边,加上相应的值 pushup( l, r, rt ); return ; } if ( l + 1 == r ) return ; //到子节点,这句一定要有!!! i64 mid = (l + r) >> 1; if ( yl <= mid ) { update( yl, yr, pd, l, mid, ls ); } if ( yr > mid ) { update( yl, yr, pd, mid, r, rs ); //这里不再是m+1,因为要进入类似[1,2][2,3]的叶子节点 } pushup( l, r, rt ); } int main() { cnt = 0; cin >> n; //左下角到右上角 auto get = [&](int x1, int y1, int x2, int y2) { u.x = x1; u.down = y1, u.up = y2, u.inout = 1; line[ ++cnt ] = u;//给入边赋值 yy[cnt] = y1;//获得y值 u.x = x2; u.down = y1, u.up = y2, u.inout = -1; line[ ++cnt ] = u; yy[cnt] = y2; }; for (i64 i = 1; i <= n; i++) { int x, y; cin >> x >> y; get(0, y - 1, x, y); get(x - 1, 0, x, y); } sort( yy + 1, yy + cnt + 1); //给yy排个序 sort( line + 1, line + cnt + 1, cmp ); //给line按照x轴方向从左到右排序 i64 length = unique( yy + 1, yy + cnt + 1 ) - (yy + 1); //进行离散化操作,unique返回重复位置指针,减去(头指针+1)是数组开始的地方得到数组长度 memset( cover, 0, sizeof( cover ) ); memset( len, 0, sizeof(len) ); i64 ans = 0; for (i64 i = 1; i <= cnt; i++) { ans += len[1] * ( line[i].x - line[i - 1].x ); i64 yl = lower_bound( yy + 1, yy + length + 1, line[i].down ) - yy; i64 yr = lower_bound( yy + 1, yy + length + 1, line[i].up ) - yy; i64 pd = line[i].inout; update( yl, yr, pd, 1, length, 1 ); } cout << ans << '\n'; return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18199853
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步