博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Trace 2018徐州icpc网络赛 (二分)(树状数组)
阅读量:5312 次
发布时间:2019-06-14

本文共 3911 字,大约阅读时间需要 13 分钟。

 

There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xxx , yyy ) means the wave is a rectangle whose vertexes are ( 000 , 000 ), ( xxx , 000 ), ( 000 , yyy ), ( xxx , yyy ). Every time the wave will wash out the trace of former wave in its range and remain its own trace of ( xxx , 000 ) -> ( xxx , yyy ) and ( 000 , yyy ) -> ( xxx , yyy ). Now the toad on the coast wants to know the total length of trace on the coast after n waves. It's guaranteed that a wave will not cover the other completely.

Input

The first line is the number of waves n(n≤50000)n(n \le 50000)n(n50000).

The next nnn lines,each contains two numbers xxx yyy ,( 0<x0 < x0<x , y≤10000000y \le 10000000y10000000 ),the iii-th line means the iii-th second there comes a wave of ( xxx , yyy ), it's guaranteed that when 1≤i1 \le i1i , j≤nj \le njn ,xi≤xjx_i \le x_jxixj and yi≤yjy_i \le y_jyiyj don't set up at the same time.

Output

An Integer stands for the answer.

Hint:

As for the sample input, the answer is 3+3+1+1+1+1=103+3+1+1+1+1=103+3+1+1+1+1=10

样例输入 复制

31 44 13 3

样例输出 复制

10

题目来源

 

比赛的时候想的是手撸一个平衡树排序,然后二分查找这个点左右两边的点,再比较他们的边值,结果数据结构写炸了

赛后看到网上题解才想起set和list 这些stl 太弱了Orz 

用set这类的话 就把一个点的边值拆成两个处理,从后往前,(后面的点总是覆盖前面),看看当今的点时候比后面的点边值高出多少

set的二分还是要%一下,毕竟没这么写过

1 #include
2 using namespace std; 3 4 typedef long long ll; 5 int n; 6 const int maxn = 5e4+5; 7 const int maxnn = 1e7+7; 8 9 vector
vec1,vec2;10 ll solve(vector
vec)11 {12 ll ans = 0;13 int sz = vec.size();14 set
st;15 for(int i=n-1;i>=0;i--)16 {17 set
::iterator it = st.lower_bound(vec[i]);18 if(it == st.begin())ans += vec[i];19 else20 {21 it--;22 ans += vec[i] - *it;23 }24 st.insert(vec[i]);25 }26 return ans;27 }28 29 int main()30 {31 scanf("%d",&n);32 int x,y;33 for(int i=1;i<=n;i++)34 {35 scanf("%d%d",&x,&y);36 vec1.push_back(x);37 vec2.push_back(y);38 }39 printf("%lld\n",solve(vec1)+solve(vec2));40 }
View Code

 

 除了可以二分之外 还有树状数组的写法,能树状数组肯定可以线段树。这里先补上树状数组的做法。

trex表示是一个记录相应x位置的y的值的前缀和,trey也类似

  那么插入(4,1)的时候 更改trex,trey, y from 0 到 1 所遇到的横向遇到x都是3;x from 0 to 3 和 from 4 to 4 对应y值不同,这样就用到树状数组的区间更新

  把query 出来的上一个位置+1的位置更新加上现在的点和之前的差值 然后在现在位置+1的位置减去  例如:trex(x在各个位置对应的y值) 3+1位置加上差值 (1-3) 4+1位置加上差值的相反数

1 #include
2 using namespace std; 3 typedef long long ll; 4 const int maxn = 5e4+5; 5 const int maxx = 1e7+5; 6 int n; 7 struct Node 8 { 9 int x,y;10 }node[maxn];11 int trex[maxx];12 int trey[maxx];13 14 int maxxx = 0;15 int lowbit(int x)16 {17 return x &(-x);18 }19 void add(int x,int val,int *tre)20 {21 for(int i=x;i<=maxxx;i+=lowbit(i))22 {23 tre[i] += val;24 }25 }26 27 int query(int x,int *tre)28 {29 int ans = 0;30 for(int i=x;i>0;i-=lowbit(i))31 {32 ans += tre[i];33 }34 return ans;35 }36 int main()37 {38 scanf("%d",&n);39 for(int i=1;i<=n;i++)40 {41 scanf("%d%d",&node[i].x,&node[i].y);42 maxxx = max(maxxx,max(node[i].x,node[i].y));43 }44 ll ans = 0;45 for(int i=n;i>0;i--)46 {47 int x = node[i].x;48 int y = node[i].y;49 int lenx = query(y,trey);50 int leny = query(x,trex);51 ans += x - lenx;52 ans += y - leny;53 int valy = query(x,trex);54 int valx = query(y,trey);55 add(valy+1,x-valx,trey);56 add(y+1,valx-x,trey);57 add(valx+1,y-valy,trex);58 add(x+1,valy-y,trex);59 //printf("%d---%d %d---%d %d----%d\n",x,y,x-valx,y-valy,valx,valy);60 }61 printf("%lld\n",ans);62 }
View Code

 

 

转载于:https://www.cnblogs.com/iwannabe/p/9615387.html

你可能感兴趣的文章
UNITY在VS中调试
查看>>
SDUTOJ3754_黑白棋(纯模拟)
查看>>
Scala入门(1)Linux下Scala(2.12.1)安装
查看>>
如何改善下面的代码 领导说了很耗资源
查看>>
Quartus II 中常见Warning 原因及解决方法
查看>>
php中的isset和empty的用法区别
查看>>
Android ViewPager 动画效果
查看>>
pip和easy_install使用方式
查看>>
博弈论
查看>>
Redis sentinel & cluster 原理分析
查看>>
我的工作习惯小结
查看>>
把word文档中的所有图片导出
查看>>
浏览器的判断;
查看>>
ubuntu 18.04取消自动锁屏以及设置键盘快捷锁屏
查看>>
Leetcode 589. N-ary Tree Preorder Traversal
查看>>
机器学习/深度学习/其他开发环境搭建记录
查看>>
xml.exist() 实例演示
查看>>
判断是否为空然后赋值
查看>>
zabbix监控日志文件
查看>>
正则表达式
查看>>