题目:http://acm.hdu.edu.cn/showproblem.php?pid=6681

题意:一个n*m的矩形蛋糕,每次给一个点(x, y)和方向dir确定一条切的线,问最后把蛋糕分成了几块,任意的x都不相同,任意的y也都不相同。

思路:观察发现,对于每条横线,每穿过一条竖线就会使蛋糕多一块。把坐标离散化后,对于方向L的线就是查找1~x内小于y的U线和大于y的D线数量;对于方向R的线就是查找x~k内小于y的U线和大于y的D线数量。区间内小于某个数的个数,考虑主席树,方向U和D分别建树。

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 1e5+5;struct T{int l, r, sum, num;}T1[maxn<<5], T2[maxn<<5];
int tot1, tot2, root1[maxn], root2[maxn];
void update1(int &now, int old, int l, int r, int pos, int v){now = ++tot1; T1[now] = T1[old]; T1[now].num += v;if(l == r) return ;int mid = l+r >> 1;if(pos <= mid) update1(T1[now].l, T1[old].l, l, mid, pos, v);else update1(T1[now].r, T1[old].r, mid+1, r, pos, v);
}
void update2(int &now, int old, int l, int r, int pos, int v){now = ++tot2; T2[now] = T2[old]; T2[now].num += v;if(l == r) return ;int mid = l+r >> 1;if(pos <= mid) update2(T2[now].l, T2[old].l, l, mid, pos, v);else update2(T2[now].r, T2[old].r, mid+1, r, pos, v);
}
int query1(int x, int y, int l, int r, int val){ // <= valif(l == r) return T1[y].num - T1[x].num;int mid = l+r >> 1;if(val <= mid) return query1(T1[x].l, T1[y].l, l, mid, val);else return T1[T1[y].l].num - T1[T1[x].l].num + query1(T1[x].r, T1[y].r, mid+1, r, val);
}
int query2(int x, int y, int l, int r, int val){ // >= valif(l == r) return T2[y].num - T2[x].num;int mid = l+r >> 1;if(val <= mid) return T2[T2[y].r].num - T2[T2[x].r].num + query2(T2[x].l, T2[y].l, l, mid, val);else return query2(T2[x].r, T2[y].r, mid+1, r, val);
}
vector<int>vec;
int getid(int x){return lower_bound(vec.begin(), vec.end(), x)-vec.begin()+1;}
struct P{int x, y, d;}p[maxn];
bool cmp(P a, P b){return a.x < b.x;};
int t, n, m, k, a[maxn];
void Q(int rt, int l, int r, int f){if(l == r){if(f == 1) cout << T1[rt].num << " ";else cout << T2[rt].num << " ";return ;} int mid = l+r >> 1;if(f==1) Q(T1[rt].l, l, mid, f), Q(T1[rt].r, mid+1, r, f);else Q(T2[rt].l, l, mid, f), Q(T2[rt].r, mid+1, r, f);
}
int main()
{cin >> t;while(t--){tot1 = tot2 = 0; vec.clear();cin >> n >> m >> k;int x, y; char op[2];for(int i=1; i<=k; i++){scanf("%d%d%s", &p[i].x, &p[i].y, op);switch(op[0]){case 'L' : p[i].d = 1; break;case 'R' : p[i].d = 2; break;case 'U' : p[i].d = 3; break;case 'D' : p[i].d = 4; break;}vec.push_back(p[i].y);}sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end());int sz = k+1; sort(p+1, p+k+1, cmp);for(int i=1; i<=k; i++) {int tmp = 0, y = getid(p[i].y);if(p[i].d == 3){update1(root1[i], root1[i-1], 1, sz, y, 1);update2(tmp, root2[i-1], 1, sz, y, 1); //复制上一个树链,相当于赋值0update2(root2[i], tmp, 1, sz, y, -1);}else if(p[i].d == 4){update1(tmp, root1[i-1], 1, sz, y, 1);update1(root1[i], tmp, 1, sz, y, -1);update2(root2[i], root2[i-1], 1, sz, y, 1);}else {update1(tmp, root1[i-1], 1, sz, y, 1);update1(root1[i], tmp, 1, sz, y, -1);update2(tmp, root2[i-1], 1, sz, y, 1);update2(root2[i], tmp, 1, sz, y, -1);}}int ans = 1;for(int i=1; i<=k; i++){if(p[i].d == 3 || p[i].d == 4) continue;int y_1 = getid(p[i].y), y_2 = getid(p[i].y);if(p[i].d == 1){ans += query1(root1[0], root1[i], 1, sz, y_1);ans += query2(root2[0], root2[i], 1, sz, y_2);}else if(p[i].d == 2){ans += query1(root1[i-1], root1[k], 1, sz, y_1);ans += query2(root2[i-1], root2[k], 1, sz, y_2);}}cout << ans << endl;}
}

HDU 6681 Rikka with Cake (可持久化线段树)相关推荐

  1. hdu - 6681 Rikka with Cake 线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意:给定一个左下顶点为,右上顶点为的矩形,然后给你k条射线,每条射线的起点及方向(上下左右)都 ...

  2. HDU 6681 Rikka with Cake(扫描线、动态开点线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意 在矩形区域内有k条射线,问这些射线将矩形分成了多少区域 题解 容易发现答案为所有射线交点个数+1. ...

  3. HDU - 6681 Rikka with Cake

    Rikka with Cake Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) P ...

  4. hdu 6681 Rikka with Cake(扫描线)

    题意:给你一个n*m的的矩形框 现在又k条射线 问这个矩形框会被分为多少个区域 思路:之前的想法是枚举边界然后线段树扫一遍计算一下矩形个数 复杂度果断不行 后面发现其实答案就是交点数+1 然后就用线段 ...

  5. hdu 4417 Super Mario(可持久化线段树)

    题意:给你一些数,有多次询问,问你在l,r区间内小于k的数有多少个 思路:主席树大发好,虽然树状数组和线段树离线也可以做 代码: #include <set> #include <m ...

  6. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  7. SP10628 COT - Count on a tree (树剖+可持久化线段树)

    题意: 给定一个包含 N 个结点的树. 树节点从 1 到 N编号..每个节点有一个整数权值. 我们会要求您执行以下操作: u v k : 询问从节点 u 到 节点 v 的路径上的第k小的权值 输入 在 ...

  8. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  9. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

最新文章

  1. 罗达克氏血液学: 临床原理与应用 Rodak‘s Hematology: Clinical Principles and Applications
  2. Linux的实际操作:用户管理(删除用户userdel userdel -r)
  3. 安装readline出现错误
  4. Android SDK 和 JDK 安装
  5. 线性回归 最小二乘推导
  6. LINUX 下 一些常用的信息显示命令:
  7. Atitit 项目战略之道 attilax著
  8. 【2019华东交通校赛:H】谁在说谎(思维)
  9. OpenGLGamma校正
  10. HTML+CSS小米注册登录界面
  11. 品荔枝赏文化,美丽乡村不一样的嘉年华
  12. [转载]Wifi OKC 验证
  13. 恩与爱是扯不开的 —— 李安
  14. dpo指标详解买入绝技_DPO指标详解:dpo指标使用技巧
  15. 给你一部电梯,如何对其进行测试?
  16. Haskell:理解Haskell中的CPS(Cont)
  17. Unity技术手册 - 粒子发射和生命周期内速度子模块
  18. html 自动填表,Delphi WEB网页自动填表
  19. python中的max_row_基于row max定位条件列值
  20. 安卓免ROOT卸载预装应用程序简要流程

热门文章

  1. 烃贝科技:Steem对妄想控盘者说88!
  2. 老年手机进水了有什么方法,手机进水了怎么处理比较好?
  3. Mysql的ER图怎么画_分享——如何画数据库ER图   王慧芬(10100340214)
  4. 自然语言处理(NLP)初识
  5. Double Dispatch and visitor patten-双重分发与访问者模式
  6. DNS云学堂 | 如何防范一本万利的DNS反射放大攻击
  7. 聚类分析:物以类聚,人以群分
  8. HDU 3271 SNIBB(数位DP+构造)
  9. Qt之实现360安全卫士主界面
  10. linux 安装 qq