用multiset集合類的時候要包含
#include<stdlib.h>
#include<set>
#include<iostream>
using namespace std;
以上一個都不能少
multiset<type, compare>
預設compare為升序,而且只有重載了<操作符的才能正常運用
對於其他類型,我們就要自訂compare結構體
struct cmp
{
bool operator()(const int& a, const int& b)const
{
return a > b;
}
};
這是一個升序結構體,bool operator()(const int& a, const int& b)const,const和括弧都不能少,否則編譯不過,因為可能集合類裡面的函數指標不匹配
對於HDU 1540,我用兩個集合類,一個升序,一個降序,每次求與該村莊x相連的村莊個數時,我們只需要求出左邊最靠近x的被摧毀村莊y和右邊最靠近x的被摧毀村莊z
z - y - 1及為與x相連的村莊個數(包括x本身),其中z,y都不能與x相同,否則x已經被摧毀,答案為0
My Code
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<set>#include<iostream>using namespace std;int n, q;int stack[50001], snum;multiset<int> myset1;multiset<int>::iterator it1;struct cmp{bool operator()(const int& a, const int& b)const{return a > b;}};multiset<int, cmp> myset2;multiset<int, cmp>::iterator it2;int main(){int i, a, temp;char str[3];while(scanf("%d%d", &n, &q) != EOF){myset1.clear();myset1.insert(0);myset1.insert(n + 1);myset2.clear();myset2.insert(0);myset2.insert(n + 1);snum = 0;for(i = 1; i <= q; i ++){scanf("%s", str);if(str[0] == 'D'){scanf("%d", &a);myset1.insert(a);myset2.insert(a);stack[++ snum] = a;}else if(str[0] == 'R'){if(snum >= 1){myset1.erase(stack[snum]);myset2.erase(stack[snum]);snum --;}}else{scanf("%d", &a);it1 = myset1.lower_bound(a);temp = *it1;if(temp == a){printf("0\n");continue;}it2 = myset2.lower_bound(a);printf("%d\n", temp - *it2 - 1);}}}return 0;}
線段樹做法代碼
#include<stdio.h>#include<string.h>struct Node{int leftD;int rightD;int left;int right;}node[210001];int n, m;int stack[51001], snum;int instack[51001];int build(int left, int right, int pre){int mid = (left + right) / 2;node[pre].left = left;node[pre].right = right;node[pre].leftD = -1;node[pre].rightD = -1;if(left == right)return 0;build(left, mid, pre * 2);build(mid + 1, right, pre * 2 + 1);return 0;}int insert(int x, int pre){int mid = (node[pre].left + node[pre].right) / 2;if(node[pre].left == node[pre].right){node[pre].leftD = x;node[pre].rightD = x;return 0;}if(x <= mid)insert(x, pre * 2);elseinsert(x, pre * 2 + 1);if(node[pre * 2].leftD != -1)node[pre].leftD = node[pre * 2].leftD;elsenode[pre].leftD = node[pre * 2 + 1].leftD;if(node[pre * 2 + 1].rightD != -1)node[pre].rightD = node[pre * 2 + 1].rightD;elsenode[pre].rightD = node[pre * 2].rightD;return 0;}int erase(int x, int pre){int mid = (node[pre].left + node[pre].right) / 2;if(node[pre].left == node[pre].right){node[pre].leftD = -1;node[pre].rightD = -1;return 0;}if(x <= mid)erase(x, pre * 2);elseerase(x, pre * 2 + 1);if(node[pre * 2].leftD != -1)node[pre].leftD = node[pre * 2].leftD;elsenode[pre].leftD = node[pre * 2 + 1].leftD;if(node[pre * 2 + 1].rightD != -1)node[pre].rightD = node[pre * 2 + 1].rightD;elsenode[pre].rightD = node[pre * 2].rightD;return 0;}int findRight(int x, int pre){int mid = (node[pre].left + node[pre].right) / 2;if(node[pre].left == node[pre].right){int temp = pre / 2;while(1){if(pre == temp * 2 && node[pre + 1].leftD != -1)return node[pre + 1].leftD;pre = temp;temp = pre / 2;}return 0;}if(x <= mid)return findRight(x, pre * 2);elsereturn findRight(x, pre * 2 + 1);return 0;}int findLeft(int x, int pre){int mid = (node[pre].left + node[pre].right) / 2;if(node[pre].left == node[pre].right){int temp = pre / 2;while(1){if(pre == temp * 2 + 1 && node[pre - 1].rightD != -1)return node[pre - 1].rightD;pre = temp;temp = pre / 2;}return 0;}if(x <= mid)return findLeft(x, pre * 2);elsereturn findLeft(x, pre * 2 + 1);return 0;}int main(){char str[10];int a;int i;while(scanf("%d%d", &n, &m) != EOF){snum = 0;build(0, n + 1, 1);insert(0, 1);insert(n + 1, 1);memset(instack, 0, sizeof(instack));for(i = 1; i <= m; i ++){scanf("%s", str);if(str[0] == 'D'){scanf("%d", &a);insert(a, 1);instack[a] = 1;stack[++ snum] = a;}else if(str[0] == 'R'){if(snum > 0){erase(stack[snum], 1);instack[stack[snum]] = 0;snum --;}}else{scanf("%d", &a);if(instack[a])printf("0\n");elseprintf("%d\n", findRight(a, 1) - findLeft(a, 1) - 1);}}}return 0;}