HDU 1540 Tunnel Warfare线段树解法及分块解法
来源:互联网 发布:淘宝宝贝创建时间 编辑:程序博客网 时间:2024/06/06 19:25
Tunnel Warfare
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9329 Accepted Submission(s): 3639
Problem Description
During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
Input
The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
Output
Output the answer to each of the Army commanders’ request in order on a separate line.
Sample Input
7 9D 3D 6D 5Q 4Q 5RQ 4RQ 4
Sample Output
1024
思路:这个题解法有两种,线段树或者暴力分块。目的都是找出询问村庄的左边界和右边界,然后直接计算出结果。
分块代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define MAX 50005using namespace std;struct Node{int left,right;}node[MAX];int Stack[MAX],top;int n,m;int area,prot;void Distory(int pos) //在破坏时,对区域进行更新(down和up之间)。{int down = pos/area*area;int up = min(n,(pos/area + 1)*area - 1);node[pos].left = node[pos].right = pos;for(int j = pos - 1; j >= down && node[j].left != node[j].right; j--)node[j].right = pos;for(int j = pos + 1; j <= up && node[j].left != node[j].right; j++)node[j].left = pos;return ;}void Rebuild(int pos) //在修复是,对区域进行更新 {int down = pos/area*area;int up = min(n,(pos/area + 1)*area - 1);int left = pos == down ? down - 1 : node[pos - 1].left,right= pos == up ? up + 1 : node[pos + 1].right;node[pos].left = left,node[pos].right = right;for(int j = pos - 1; j >= down && node[j].left != node[j].right; j--)node[j].right = right;for(int j = pos + 1; j <= up && node[j].left != node[j].right; j++)node[j].left = left;return ;}int find_left(int pos) //找到左边界 {return (node[pos].left == pos || node[pos].left == -1) ? node[pos].left : find_left(node[pos].left);}int find_right(int pos) //找到右边界 {return (node[pos].right == pos || node[pos].right == n) ? node[pos].right : find_right(node[pos].right);}void PUT(){for(int j = 0; j < n; j++)cout << node[j].left << "|" << node[j].right << endl;}int main( ){while(scanf("%d%d",&n,&m) != EOF){top = 0;area = sqrt(n);if(n%area > 0) area++;for(int j = 0; j < area; j++) //先做分块预处理,之后的所有处理都在对应块中进行 for(int k = 0; k < area; k++)node[area*j + k].left = area*j - 1,node[area*j + k].right = min(area*(j + 1),n);while(m--){getchar();char c = getchar();int poit;if(c == 'D'){scanf("%d",&poit);poit--;Distory(poit);Stack[top++] = poit;}if(c == 'Q'){scanf("%d",&poit);poit--;int ans = find_right(poit) - find_left(poit) - 1;printf("%d\n",ans == -1 ? 0 : ans);}if(c == 'R'){poit = Stack[--top];Rebuild(poit);}}}return 0;}分块就是O(n)暴力的优化,优化后的复杂度是O(sqrt(n))。在此处的复杂度一共是O(m*sqrt(n)).。
线段树代码:
#include<iostream>#include<cstring>#include<cstdio>#define MAX 50004using namespace std;struct Node{int left,mid,right;bool OK;}Tree[MAX*3];int Stack[MAX],top;int node_tree[MAX];int l,r,n,m;void BuildTree(int left,int right,int pos) //建树 {Tree[pos].left = left,Tree[pos].right = right;Tree[pos].mid = (left + right) >> 1;Tree[pos].OK = true;if(left == right){node_tree[left] = pos;return ;}BuildTree(left,(right + left)>>1,pos<<1);BuildTree(((right + left)>>1) + 1,right,(pos<<1) + 1);return ;}void DistoryNode(int pos) //在破坏时更新 {Tree[pos].OK = false;if(pos == 1) return ;DistoryNode(pos>>1);}void RebuildNode(int pos) //在修复是更新 {Tree[pos].OK = true;if(pos == 1 || !Tree[pos^1].OK) return ;RebuildNode(pos>>1);}void LeftQueryTree(int node,int pos); //寻找区间内最左边的被破坏的村庄 void RightQueryTree(int node,int pos);//寻找区间内最右边的被破坏的村庄 int main( ){while(cin >> n >> m){BuildTree(1,n,1);while(m--){getchar(); char c = getchar();int node;if(c == 'D'){scanf("%d",&node);Stack[top++] = node;DistoryNode(node_tree[node]);}if(c == 'Q'){scanf("%d",&node);l = 0;RightQueryTree(node,1);//左边界在[1,node]区间中最右边的点 r = n + 1;LeftQueryTree(node,1); //右边界在[node,n - 1]区间中最左边的点 int ans = 0;if(l == r) ans = 0;else ans = r - l - 1;printf("%d\n",ans);}if(c == 'R'){node = Stack[--top];RebuildNode(node_tree[node]);}}}return 0;}void RightQueryTree(int node,int pos){if(Tree[pos].OK || l != 0){return ;}if(Tree[pos].left == Tree[pos].right){if(!Tree[pos].OK) l = Tree[pos].left;return;}if(Tree[pos].mid < node){RightQueryTree(node,pos<<1|1); //优先搜索右子树 }RightQueryTree(node,pos<<1); return ;}void LeftQueryTree(int node,int pos){if(Tree[pos].OK || r != n + 1){return ;}if(Tree[pos].left == Tree[pos].right){if(!Tree[pos].OK) r = Tree[pos].left;return ;}if(Tree[pos].mid >= node){LeftQueryTree(node,pos<<1); //优先搜索左子树 }LeftQueryTree(node,pos<<1|1);return ; }线段树做法每步操作的复杂度O(log(n)),总复杂度是O(m*log(n))。
这个是线段树模板题,所以往上的很多题解也都是线段树。而这个题的数据量完全可以用分块解决,所以,我就自己把这个题再拉出来鞭尸,在多写一个分块题解。
阅读全文
0 0
- HDU 1540 Tunnel Warfare线段树解法及分块解法
- (两种解法)hdu 1540 Tunnel Warfare (线段树区间合并)
- hdu 1540 Tunnel Warfare 线段树
- hdu-1540-Tunnel Warfare-线段树
- 【HDU】 1540 Tunnel Warfare 线段树
- hdu 1540 Tunnel Warfare【线段树】
- hdu 1540 Tunnel Warfare(线段树)
- HDU 1540 Tunnel Warfare(线段树)
- HDU 1540 Tunnel Warfare 线段树
- HDU 1540 Tunnel Warfare [二分 + 线段树]
- HDU 1540 Tunnel Warfare (线段树)
- hdu 1540 Tunnel Warfare 线段树 / set
- hdu Tunnel Warfare(线段树)
- HDU 1540Tunnel Warfare Tunnel Warfare (线段树- 区间合并-单点更新查询)
- HDU 1540 Tunnel Warfare 【线段树--最大连续区间】
- hdu 1540 Tunnel Warfare(线段树 连续区间)
- POJ 2892 & HDU 1540 Tunnel Warfare (线段树)
- hdu 1540 Tunnel Warfare(线段树区间统计)
- ShareSDKUtils,封装的分享工具类,使用默认的GUI或者自定义分享某个平台
- [NOIP提高组2000]单词接龙
- nyoj746 整数划分(四)
- C# DevExpress实现搜索智能提示功能
- java下划线命名转驼峰命名
- HDU 1540 Tunnel Warfare线段树解法及分块解法
- hdu6016二分图思路
- Linux下glib源码安装使用方法
- Bootstrap模版框架怎么用
- 10款超好用的开源大数据分析工具
- Struts2 + spring 环境搭建
- 欢迎使用CSDN-markdown编辑器
- 【区间dp】Treats for the Cows POJ
- ContextLoaderListener作用详解