HDU 1166 敌兵布阵
单调更新区间查询和
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 50010; const int INF = 0x3f3f3f3f; struct node { int l,r; int sum; }tree[MAXN * 4]; int src[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].sum = src[l]; return; } int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; } void update(int id,int pos,int val) { if (tree[id].l == pos && tree[id].r == pos) { tree[id].sum += val; return; } int mid = (tree[id].l + tree[id].r) / 2; if (pos <= mid) update(id * 2,pos,val); else update(id * 2 + 1,pos,val); tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; } int query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].sum; } int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return query(id * 2 + 1,l,r); else if (r <= mid) return query(id * 2,l,r); else { return query(id * 2 ,l,mid) + query(id * 2 + 1,mid + 1,r); } } int main() { int T,kase = 1; scanf("%d",&T); while (T--) { int N; scanf("%d",&N); for (int i = 1 ; i <= N ; i++) scanf("%d",&src[i]); build(1,1,N); printf("Case %d:\n",kase++); char op[10]; while(scanf("%s",op) != EOF) { if (op[0] == ‘E‘) break; if (op[0] == ‘Q‘) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(1,l,r)); } if (op[0] == ‘A‘) { int x,val; scanf("%d%d",&x,&val); update(1,x,val); } if(op[0] == ‘S‘) { int x,val; scanf("%d%d",&x,&val); update(1,x,-val); } } } return 0; }
HDU 1754 I Hate It
单点更新区间查询最值
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 200010; const int INF = 0x3f3f3f3f; struct node { int l,r; int val; }tree[MAXN * 4]; int src[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].val = src[l]; return; } int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); tree[id].val = max(tree[id * 2].val,tree[id * 2 + 1].val); } void update(int id,int pos,int val) { if (tree[id].l == pos && tree[id].r == pos) { tree[id].val = val; return; } int mid = (tree[id].l + tree[id].r) / 2; if (pos <= mid) update(id * 2,pos,val); else update(id * 2 + 1,pos,val); tree[id].val = max(tree[id * 2].val,tree[id * 2 + 1].val); } int query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].val; } int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return query(id * 2 + 1,l,r); else if (r <= mid) return query(id * 2,l,r); else { return max(query(id * 2,l,mid) ,query(id * 2 + 1,mid + 1,r)); } } int main() { int N,Q; while (scanf("%d%d",&N,&Q) != EOF) { for (int i = 1 ; i <= N; i++) scanf("%d",&src[i]); build(1,1,N); while (Q--) { char op[5]; scanf("%s",op); if (op[0] == ‘Q‘) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(1,l,r)); } else { int x,val; scanf("%d%d",&x,&val); update(1,x,val); } } } return 0; }
POJ 3468 A Simple Problem with Integers
区间更新区间求和。
这里就要涉及到懒操作。注意的是lazy被更新的区间一定是当前的区间和已经更新完
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct node { int l,r; LL lazy,sum; }tree[MAXN * 4]; LL src[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].lazy = 0; if (l == r) { tree[id].sum = src[l]; return; } int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid +1,r); tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; } void push_down(int id) { if (tree[id].lazy == 0) return; tree[id * 2].sum += (tree[id * 2].r - tree[id * 2].l + 1) * tree[id].lazy; tree[id * 2].lazy += tree[id].lazy; tree[id * 2 + 1].sum += (tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1) * tree[id].lazy; tree[id * 2 + 1].lazy += tree[id].lazy; tree[id].lazy = 0; } void update(int id,int l,int r,LL val) { if (tree[id].l >= l && tree[id].r <= r) { tree[id].lazy += val; tree[id].sum += val * (r - l + 1); return; } push_down(id); int mid = (tree[id].r + tree[id].l) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2 ,l,r,val); else { update(id * 2,l,mid,val); update(id * 2 + 1,mid + 1,r,val); } tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; } LL query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].sum; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return query(id * 2 + 1,l,r); else if (r <= mid) return query(id * 2,l,r); else { return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r); } } int main() { int N,Q; while (scanf("%d%d",&N,&Q) != EOF) { for (int i = 1 ; i <= N ; i++) scanf("%I64d",&src[i]); build(1,1,N); char op[10]; while (Q--) { scanf("%s",op); if (op[0] == ‘Q‘) { int l,r; scanf("%d%d",&l,&r); printf("%I64d\n",query(1,l,r)); } else { int l,r; LL val; scanf("%d%d%I64d",&l,&r,&val); update(1,l,r,val); } } } return 0; }
POJ 2528 Mayor‘s posters
区间更新为一个值。然后统计有哪些数出现过
注意需要离散化,且不能随便离散化。
线段树是点操作。这里对长度为1的段进行操作。也就是将一个长度为1的段视作一个点,举个例子
区间为 1-10,1--4,5 -- 10
区间为 1--10,1--4,6-10;
一般的离散化是变成了这样 1离散为1,4离散为2,5离散为3,10离散为4
区间都变成了1-4,1--2,3 -- 4;
显然上面2中答案是不一样的。随便离散是WA的。第一个答案是2,第二个答案是3
那么如何改,方案是如果两个相邻的点差值大于1,那么中间就插入一个点。
那么按照这种离散上面变成了有6个点1,3,4,5,9,10,离散成了1-6,1-3,4-6 答案为2
和第二组问题 变成这样几个点1 3 4 5 6 9 10 离散成了 1--7,1--3,5--7答案为3
代码
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 10010; map<int,int>mp,res; struct point { int l,r; int idx; }src[MAXN]; struct node { int l,r; int val; bool flag; }tree[MAXN * 16]; int ori[MAXN * 2],newdata[MAXN * 4]; void build(int id,int l,int r) { tree[id].l = newdata[l]; tree[id].r = newdata[r]; tree[id].val = -1; tree[id].flag = false; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_down(int id) { if (tree[id].flag) { tree[id * 2].flag = tree[id * 2 + 1].flag = true; tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val; tree[id].flag = false; } } void update(int id,int l,int r,int val) { if (r < tree[id].l || l > tree[id].r) return; if (tree[id].l >= l && tree[id].r <= r) { tree[id].val = val; tree[id].flag = true; return; } push_down(id); /*int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2,l,r,val); else { update(id * 2 ,l,mid,val); update(id * 2 + 1,mid + 1,r,val); }*/ update(id * 2,l,r,val); update(id * 2 + 1,l,r,val); } void query(int id,int l,int r,int &ret) { if (tree[id].l == tree[id].r) { if (mp[tree[id].val] == 0 && tree[id].val != -1) { ret++; // printf("%d\n",tree[id].val); mp[tree[id].val] = 1; } return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; query(id * 2,l,mid,ret); query(id * 2 + 1,mid + 1,r,ret); } int main() { int T; scanf("%d",&T); while (T--) { mp.clear(); res.clear(); int N; scanf("%d",&N); int cas = 0; for (int i = 1; i <= N ; i++) { scanf("%d%d",&src[i].l,&src[i].r); src[i].idx = i; ori[++cas] = src[i].l; ori[++cas] = src[i].r; } sort(ori + 1,ori + 1 + cas); int leap = 0; ori[0] = -1; for (int i = 1; i <= cas ; i++) { if (ori[i] != ori[i - 1]) ori[++leap] = ori[i]; } cas = 0; newdata[++cas] = ori[1]; for (int i = 2 ; i <= leap ; i++) { if (ori[i] > ori[i - 1] + 1) { newdata[++cas] = ori[i] - 1; newdata[++cas] = ori[i]; } else { newdata[++cas] = ori[i]; } } // printf("%d\n",cas); //for (int i = 1 ; i <= cas ; i++) // printf("%d ",newdata[i]); putchar(‘\n‘); build(1,1,cas); for (int i = 1 ; i <= N ; i++) { update(1,src[i].l,src[i].r,src[i].idx); } int ret = 0; query(1,1,cas,ret); printf("%d\n",ret); } return 0; }
hdu 1698 Just a Hook
记得题意是如果一个区间值全部相等,那么权就是这个区间的长度乘以这个值,最开始全都是1
用一个sta记录这个区间是不是所值都相等然后做
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct node { int l,r; bool sta; int val; bool flag; }tree[MAXN * 4]; int L; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].val = 1; tree[id].flag = false; tree[id].sta = true; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_down(int id) { if (tree[id].flag) { tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val; tree[id * 2].flag = true; tree[id * 2 + 1].flag = true; tree[id].flag = false; tree[id].sta = true; tree[id * 2].sta = true; tree[id * 2 + 1].sta = true; } } void push_up(int id) { if (tree[id * 2].sta == true && tree[id * 2 + 1].sta == true) { if (tree[id * 2].val == tree[id * 2 + 1].val) { tree[id].val = tree[id * 2 + 1].val; tree[id].sta = true; } else tree[id].sta = false; } else tree[id].sta = false; } void update(int id,int l,int r,int val) { if (tree[id].l >= l && tree[id].r <= r) { tree[id].flag = true; tree[id].val = val; tree[id].sta = true; return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2,l,r,val); else { update(id * 2,l,mid,val); update(id * 2 + 1,mid + 1,r,val); } push_up(id); } int query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { if (tree[id].sta == true) { // printf("%d %d %d\n",tree[id].l,tree[id].r,tree[id].val); return tree[id].val * (tree[id].r - tree[id].l + 1); } } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return query(id * 2 + 1,l,r); else if (r <= mid) return query(id * 2,l,r); else { return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r); } } int main() { int T,kase = 1; scanf("%d",&T); while (T--) { scanf("%d",&L); build(1,1,L); int Q; scanf("%d",&Q); while (Q--) { int l,r,val; scanf("%d%d%d",&l,&r,&val); update(1,l,r,val); //printf("%d %d %d\n",l,r,val); } printf("Case %d: The total value of the hook is %d.\n",kase++,query(1,1,L)); } return 0; }
ZOJ 1610 Count the Colors
只有一次查询。可以直接暴力出来修改后最后每个点的颜色。然后扫一遍
我第一次的做法不知道为何就是老WA。求好心人告知。
下面是参照别人A的代码
结构体的COL表示染了什么颜色
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 8110; struct node { int l,r,col; }tree[MAXN * 4]; int cnt[MAXN],col[MAXN],N; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].col = -1; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_down(int id) { if (tree[id].col != -1) { tree[id * 2].col = tree[id * 2 + 1].col = tree[id].col; tree[id].col = -1; } } void update(int id,int l,int r,int val) { if (tree[id].l >= l && tree[id].r <= r) { tree[id].col = val; //printf("%d %d %d\n",tree[id].l,tree[id].r,tree[id].col); return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2,l,r,val); else { update(id * 2,l,mid,val); update(id * 2 + 1,mid + 1,r,val); } } void query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { //printf("%d\n",tree[id].col); if (tree[id].col != -1) { //printf("%d\n",tree[id].col); for (int i = tree[id].l ; i <= tree[id].r ; i++) col[i] = tree[id].col; return; } } push_down(id); if (l == r) return; int mid = (tree[id].l + tree[id].r ) / 2; if (l > mid) query(id * 2 + 1,l,r); else if (r <= mid) query(id * 2,l,r); else { query(id * 2,l,mid); query(id * 2 + 1,mid + 1,r); } } int main() { while (scanf("%d",&N) != EOF) { memset(cnt,0,sizeof(cnt)); build(1,1,8000); for (int i = 1 ; i <= N ; i++) { int l,r,val; scanf("%d%d%d",&l,&r,&val); update(1,l + 1,r,val); } memset(col,-1,sizeof(col)); query(1,1,8000); int pre = -1; for (int i = 0 ; i <= 8000 ; i++) { if (col[i] == -1) { pre = -1; continue; } if (pre != col[i]) { cnt[col[i]]++; pre = col[i]; } } for (int i = 0 ; i <= 8000 ; i++) { if (cnt[i]) printf("%d %d\n",i,cnt[i]); } puts(""); } return 0; }
下面是我自己WA的代码在查询中就更新出答案不知道那里有问题
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 8110; const int INF = 0x3f3f3f3f; struct node { int l,r; bool flag,sta; int val; }tree[MAXN * 4]; int N; int cnt[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].val = -1; tree[id].flag = false; tree[id].sta = true; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_down(int id) { if (tree[id].flag) { tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val; tree[id * 2].flag = true; tree[id * 2 + 1].flag = true; tree[id].flag = false; tree[id].sta = true; tree[id * 2].sta = true; tree[id * 2 + 1].sta = true; } } void push_up(int id) { if (tree[id * 2].sta == true && tree[id * 2 + 1].sta == true) { if (tree[id * 2].val == tree[id * 2 + 1].val) { tree[id].val = tree[id * 2 + 1].val; tree[id].sta = true; } else tree[id].sta = false; } else tree[id].sta = false; } void update(int id,int l,int r,int val) { if (tree[id].l >= l && tree[id].r <= r) { tree[id].flag = true; tree[id].val = val; tree[id].sta = true; return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2,l,r,val); else { update(id * 2,l,mid,val); update(id * 2 + 1,mid + 1,r,val); } push_up(id); } void query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { if (tree[id].sta == true) { if (tree[id].val != -1) { cnt[tree[id].val]++; //a printf("%d\n",tree[id].val); } return; } } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) query(id * 2 + 1,l,r); else if (r <= mid) query(id * 2 ,l,r); else { query(id * 2,l,mid); query(id * 2 + 1,mid + 1,r); } } int main() { //freopen("sample.txt","r",stdin); while (scanf("%d",&N) != EOF) { build(1,1,8010); for (int i = 1 ; i <= N ; i++) { int l,r,val; scanf("%d%d%d",&l,&r,&val); if (l > r) swap(l,r); if (l == r) continue; update(1,l + 1,r,val); } memset(cnt,0,sizeof(cnt)); query(1,1,8010); for (int i = 0 ; i <= 8010 ; i++) { if (cnt[i] == 0) continue; printf("%d %d\n",i,cnt[i]); } puts(""); } return 0; }
POJ 3264 Balanced Lineup
查询区间最大最小值。
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 50010; struct node { int l,r,MIN,MAX; }tree[MAXN * 4]; int src[MAXN],N; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].MIN = tree[id].MAX = src[l]; return; } int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); tree[id].MIN = min(tree[id * 2].MIN,tree[id * 2 + 1].MIN); tree[id].MAX = max(tree[id * 2].MAX,tree[id * 2 + 1].MAX); } int querymax(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].MAX; } int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return querymax(id * 2 + 1,l,r); else if (r <= mid) return querymax(id * 2,l,r); else { return max(querymax(id * 2,l,mid),querymax(id * 2 + 1,mid + 1,r)); } } int querymin(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].MIN; } int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return querymin(id * 2 + 1,l,r); else if (r <= mid) return querymin(id * 2,l,r); else { return min(querymin(id * 2,l,mid),querymin(id * 2 + 1,mid + 1,r)); } } int main() { int Q; while (scanf("%d%d",&N,&Q) != EOF) { for (int i = 1 ; i <= N ; i++) scanf("%d",&src[i]); build(1,1,N); while (Q--) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",querymax(1,l,r) - querymin(1,l,r)); } } return 0; }
HDU 4027 Can you answer these queries?
每次操作把区间内所有值开跟好向下取整,最大的数最多开7次根到1,所以直接做区间长度等于区间和直接结束
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct node { int l,r; LL sum; bool flag; }tree[MAXN * 4]; LL src[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].sum = src[l]; return; } int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; } void push_down(int id) { if (tree[id].l == tree[id].r) { tree[id].sum = (LL)sqrt(1.0 * tree[id].sum); return; } push_down(id * 2); push_down(id * 2 + 1); tree[id].sum = tree[id * 2 + 1].sum + tree[id * 2].sum; } void update(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { if (tree[id].sum == (LL)(tree[id].r - tree[id].l + 1)) return; push_down(id); return; } int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r); else if (r <= mid) update(id * 2,l,r); else { update(id * 2,l,mid); update(id * 2 + 1,mid + 1,r); } tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; } LL query(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].sum; } int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return query(id * 2 + 1,l,r); else if (r <= mid) return query(id * 2,l,r); else { return query(id * 2,l,mid) + query(id * 2 + 1,mid + 1,r); } } int main() { int N,M,kase = 1; while (scanf("%d",&N) != EOF) { for (int i = 1 ; i <= N ; i++) scanf("%I64d",&src[i]); scanf("%d",&M); build(1,1,N); printf("Case #%d:\n",kase++); while (M--) { int op; scanf("%d",&op); if (op == 0) { int l,r; scanf("%d%d",&l,&r); if (l > r) swap(l,r); update(1,l,r); } else { int l,r; scanf("%d%d",&l,&r); if (l > r) swap(l,r); printf("%I64d\n",query(1,l,r)); } } putchar(‘\n‘); } return 0; }
HDU 1540 Tunnel Warfare
维护左连续长,右连续长,最大连续长度
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 50010; const int INF = 0x3f3f3f3f; struct node { int l,r; int leftlen,rightlen,maxlen; }tree[MAXN * 4]; stack<int>s; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].leftlen = tree[id].rightlen = tree[id].maxlen = r - l + 1; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_up(int id) { //leftlen; if (tree[id * 2].leftlen == tree[id * 2].r - tree[id * 2].l + 1) { tree[id].leftlen = tree[id * 2].r - tree[id * 2].l + 1 + tree[id * 2 + 1].leftlen; } else tree[id].leftlen = tree[id * 2].leftlen; //right len if (tree[id * 2 + 1].rightlen == tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1) { tree[id].rightlen = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1 + tree[id * 2].rightlen; } else tree[id].rightlen = tree[id * 2 + 1].rightlen; tree[id].maxlen = max(tree[id * 2].maxlen,tree[id * 2 + 1].maxlen); tree[id].maxlen = max(tree[id].maxlen,tree[id * 2].rightlen + tree[id * 2 + 1].leftlen); } void update(int id,int pos,bool flag) { if (tree[id].l == tree[id].r) { if (flag) tree[id].maxlen = tree[id].leftlen = tree[id].rightlen = 0; else tree[id].maxlen = tree[id].leftlen = tree[id].rightlen = 1; return; } int mid = (tree[id].l + tree[id].r) / 2; if (pos > mid) update(id * 2 + 1,pos,flag); if (pos <= mid) update(id * 2,pos,flag); push_up(id); } int query(int id,int pos) { if (tree[id].l == tree[id].r || tree[id].maxlen == tree[id].r - tree[id].l + 1) { return tree[id].maxlen; } int mid = (tree[id].l + tree[id].r) / 2; if (pos <= mid)//左半段 { int tmppos = tree[id * 2].r - tree[id * 2].rightlen + 1; if (pos >= tmppos) return tree[id * 2].rightlen + tree[id * 2 + 1].leftlen; else return query(id * 2,pos); } else { int tmppos = tree[id * 2 + 1].l + tree[id * 2 + 1].leftlen - 1; if (pos <= tmppos) return tree[id * 2 + 1].leftlen + tree[id * 2].rightlen; else return query(id * 2 + 1,pos); } } int main() { //freopen("sample.txt","r",stdin); int N,Q; while (scanf("%d%d",&N,&Q) != EOF) { build(1,1,N); while (!s.empty()) s.pop(); while (Q--) { char op[5]; scanf("%s",op); if (op[0] == ‘D‘) { int pos; scanf("%d",&pos); s.push(pos); update(1,pos,true); } if (op[0] == ‘Q‘) { int pos; scanf("%d",&pos); printf("%d\n",query(1,pos)); } if (op[0] == ‘R‘) { if (s.empty()) continue; int x = s.top(); s.pop(); update(1,x,false); } } } return 0; }
HDU 3794 Assign the task
其实就一个树形转线性
别的随便做,代码里有排除爆炸手写的树形转线性存一下模版
#pragma comment(linker, "/STACK:102400000,102400000") #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 50010; int L[MAXN],R[MAXN]; const int INF = 0x3f3f3f3f; struct node { int l,r; int val; bool flag; }tree[MAXN * 4]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].val = -1; tree[id].flag = false; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_down(int id) { if (tree[id].flag) { tree[id * 2].flag = tree[id * 2 + 1].flag = true; tree[id * 2].val = tree[id * 2 + 1].val = tree[id].val; tree[id].flag = false; } } void update(int id,int l,int r,int val) { if (tree[id].l >= l && tree[id].r <= r) { tree[id].flag = true; tree[id].val = val; return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2,l,r,val); else { update(id * 2,l,mid,val); update(id * 2 + 1,mid + 1,r,val); } } int query(int id,int pos) { if (tree[id].l == pos && tree[id].r == pos) { return tree[id].val; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (pos > mid) return query(id * 2 + 1,pos); else return query(id * 2,pos); } /* int Stack[MAXN * 2],top; int deg[MAXN]; int Index,seq[MAXN]; bool vis[MAXN]; queue<int>q[MAXN]; void get_seq(int st)//这段先序遍历树形转线性我应该是不会的 { int pos; int idx = 0; top = 1; Stack[top] = st; memset(vis,false,sizeof(vis)); while (top) { pos = Stack[top]; if (!vis[pos]) { vis[pos] = true; seq[++idx] = pos; L[pos] = idx; } if (!q[pos].empty()) { Stack[++top] = q[pos].front(); q[pos].pop(); } else { R[pos] = idx; top--; } } }*/ vector<int>q[MAXN]; int Index; int deg[MAXN]; bool vis[MAXN]; void get_seq(int u) { L[u] = ++Index; vis[u] = true; for (int i = 0 ; i < (int)q[u].size() ; i++) { int v = q[u][i]; if (vis[v]) continue; get_seq(v); } R[u] = Index; } int main() { //freopen("sample.txt","r",stdin); int T,kase = 1; scanf("%d",&T); int N,Q; while(T--) { memset(deg,0,sizeof(deg)); scanf("%d",&N); for (int i = 1 ; i <= N ; i++) q[i].clear(); for (int i = 1 ; i < N ; i++) { int u,v; scanf("%d%d",&u,&v); //q[v].push(u); q[v].push_back(u); deg[u]++; } build(1,1,N); int root = 1; for (int i = 1 ; i <= N ; i++) { if (deg[i] == 0) { root = i; break; } } Index = 0; memset(vis,false,sizeof(vis)); //printf("%d\n",root); get_seq(root); printf("Case #%d:\n",kase++); //for (int i = 1 ; i <= N ; i++) printf("%d %d\n",L[i],R[i]); scanf("%d",&Q); while (Q--) { char op[5]; scanf("%s",op); if (op[0] == ‘C‘) { int x; scanf("%d",&x); printf("%d\n",query(1,L[x])); } else { int x,val; scanf("%d%d",&x,&val); //printf("%d %d\n",L[x],R[x]); update(1,L[x],R[x],val); } } } return 0; }
HDU 4578 Transformation
这题很吊看这里 http://www.cnblogs.com/Commence/p/4871352.html
HDU 4614 Vases and Flowers
如果某个点可以插花,那么这个点值为1,由于他就是从左往右一直插花,实际上就是二分+区间和的问题。
然后查询一个区间最左边的1和最右边的1
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 50010; const int INF = 0x3f3f3f3f; struct node { int l,r; int sum,lazy,lft,rht; }tree[MAXN * 4]; int N,Q; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].sum = r - l + 1; tree[id].lft = l; tree[id].rht = r; tree[id].lazy = 0; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_up(int id) { if (tree[id].l == tree[id].r) return; tree[id].sum = tree[id * 2].sum + tree[id * 2 + 1].sum; if (tree[id * 2].lft != -1) tree[id].lft = tree[id * 2].lft; else tree[id].lft = tree[id * 2 + 1].lft; if (tree[id * 2 + 1].rht != -1) tree[id].rht = tree[id * 2 + 1].rht; else tree[id].rht = tree[id * 2].rht; } void push_down(int id) { if (tree[id].l == tree[id].r) return; if (tree[id].lazy == 1) { tree[id * 2].lft = tree[id * 2].l; tree[id * 2].rht = tree[id * 2].r; tree[id * 2].sum = tree[id * 2].r - tree[id * 2].l + 1; tree[id * 2].lazy = 1; tree[id * 2 + 1].lft = tree[id * 2 + 1].l; tree[id * 2 + 1].rht = tree[id * 2 + 1].r; tree[id * 2 + 1].sum = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1; tree[id * 2 + 1].lazy = 1; } if (tree[id].lazy == -1) { tree[id * 2].lft = -1; tree[id * 2].rht = -1; tree[id * 2].sum = 0; tree[id * 2].lazy = -1; tree[id * 2 + 1].lft = -1; tree[id * 2 + 1].rht = -1; tree[id * 2 + 1].sum = 0; tree[id * 2 + 1].lazy = -1; } tree[id].lazy = 0; } void update(int id,int l,int r,int val) { if (tree[id].l >= l && tree[id].r <= r) { if (val == 0) { if (tree[id].sum == 0) return; tree[id].sum = 0; tree[id].lft = -1; tree[id].rht = -1; tree[id].lazy = -1; return; } else if (val == 1) { if (tree[id].r - tree[id].l + 1 == tree[id].sum) return; tree[id].sum = tree[id].r - tree[id].l + 1; tree[id].lazy = 1; tree[id].lft = tree[id].l; tree[id].rht = tree[id].r; return; } } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r,val); else if (r <= mid) update(id * 2,l,r,val); else { update(id * 2,l,mid,val); update(id * 2 + 1,mid + 1,r,val); } push_up(id); } int getsum(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].sum; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return getsum(id * 2 + 1,l,r); else if (r <= mid) return getsum(id * 2,l,r); else { return getsum(id * 2,l,mid) + getsum(id * 2 + 1,mid + 1,r); } } int queryleft(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].lft; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return queryleft(id * 2 + 1,l,r); else if (r <= mid) return queryleft(id * 2,l,r); else { int ret; ret = queryleft(id * 2,l,mid); if (ret != -1) return ret; ret = queryleft(id * 2 + 1,mid + 1,r); return ret; } } int queryright(int id,int l,int r) { if (tree[id].l >= l && tree[id].r <= r) { return tree[id].rht; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) return queryright(id * 2 + 1,l,r); else if (r <= mid) return queryright(id * 2,l,r); else { int ret = queryright(id * 2 + 1,mid + 1,r); if (ret != -1) return ret; return queryright(id * 2,l,mid); } } int binseach(int A,int F) { int tmp = getsum(1,A,N); if (tmp == 0) return - 1; if (tmp < F) return N; int l = A,r = N; while (l < r) { int mid = (l + r) / 2; int val = getsum(1,A,mid); if (val >= F) { r = mid; } else l = mid + 1; } return l; } int main() { int T; scanf("%d",&T); while (T--) { scanf("%d%d",&N,&Q); build(1,1,N); while (Q--) { int op; scanf("%d",&op); if (op == 1) { int A,F; scanf("%d%d",&A,&F); A++; int tmp = binseach(A,F); if (tmp == -1) { puts("Can not put any one."); continue; } printf("%d %d\n",queryleft(1,A,tmp) - 1,queryright(1,A,tmp) - 1); update(1,A,tmp,0); } else { int l,r; scanf("%d%d",&l,&r); l++; r++; printf("%d\n",r - l + 1 - getsum(1,l,r)); update(1,l,r,1); } } putchar(‘\n‘); } return 0; }
HDU 4553 约会安排
一个优先级问题,优先女神,然后吊斯
女神的询问中先在吊死中找如果吊死中可以满足就同时更新吊死和女神的那个区间值详情看代码
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct node { int l,r; int lmax,rmax,mmax; int lmax1,rmax1,mmax1; }tree[MAXN * 4]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].lmax = tree[id].rmax = tree[id].mmax = r - l + 1; tree[id].lmax1 = tree[id].rmax1 = tree[id].mmax1 = r - l + 1; if (l == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid + 1,r); } void push_up(int id) { if (tree[id].r == tree[id].l) return; tree[id].lmax = tree[id * 2].lmax; if (tree[id * 2].lmax == tree[id * 2].r - tree[id * 2].l + 1) tree[id].lmax += tree[id * 2 + 1].lmax; tree[id].rmax = tree[id * 2 + 1].rmax; if (tree[id * 2 + 1].rmax == tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1) tree[id].rmax += tree[id * 2].rmax; tree[id].mmax = max(tree[id * 2].mmax,tree[id * 2 + 1].mmax); tree[id].mmax = max(tree[id].mmax,tree[id * 2].rmax + tree[id * 2 + 1].lmax); tree[id].lmax1 = tree[id * 2].lmax1; if (tree[id * 2].lmax1 == tree[id * 2].r - tree[id * 2].l + 1) tree[id].lmax1 += tree[id * 2 + 1].lmax1; tree[id].rmax1 = tree[id * 2 + 1].rmax1; if (tree[id * 2 + 1].rmax1 == tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1) tree[id].rmax1 += tree[id * 2].rmax1; tree[id].mmax1 = max(tree[id * 2].mmax1,tree[id * 2 + 1].mmax1); tree[id].mmax1 = max(tree[id].mmax1,tree[id * 2].rmax1 + tree[id * 2 + 1].lmax1); } void push_down(int id) { if (tree[id].l == tree[id].r) return; if (tree[id].mmax == 0) { tree[id * 2].lmax = tree[id * 2].rmax = tree[id * 2].mmax = 0; tree[id * 2 + 1].lmax = tree[id * 2 + 1].rmax = tree[id * 2 + 1].mmax = 0; } if (tree[id].mmax == tree[id].r - tree[id].l + 1) { tree[id * 2].lmax = tree[id * 2].rmax = tree[id * 2].mmax = tree[id * 2].r - tree[id * 2].l + 1; tree[id * 2 + 1].lmax = tree[id * 2 + 1].rmax = tree[id * 2 + 1].mmax = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1; } if (tree[id].mmax1 == 0) { tree[id * 2].lmax1 = tree[id * 2].rmax1 = tree[id * 2].mmax1 = 0; tree[id * 2 + 1].lmax1 = tree[id * 2 + 1].rmax1 = tree[id * 2 + 1].mmax1 = 0; } if (tree[id].mmax1 == tree[id].r - tree[id].l + 1) { tree[id * 2].lmax1 = tree[id * 2].rmax1 = tree[id * 2].mmax1 = tree[id * 2].r - tree[id * 2].l + 1; tree[id * 2 + 1].lmax1 = tree[id * 2 + 1].rmax1 = tree[id * 2 + 1].mmax1 = tree[id * 2 + 1].r - tree[id * 2 + 1].l + 1; } } int query(int id,int x) { if (tree[id].mmax < x) return 0; if (tree[id].lmax >= x) return tree[id].l; if (tree[id * 2].mmax >= x) return query(id * 2,x); if (tree[id * 2].rmax + tree[id * 2 + 1].lmax >= x) return tree[id * 2].r- tree[id * 2].rmax + 1; return query(id * 2 + 1,x); } int query1(int id,int x) { if (tree[id].mmax1 < x) return 0; if (tree[id].lmax1 >= x) return tree[id].l; if (tree[id * 2].mmax1 >= x) return query1(id * 2,x); if (tree[id * 2].rmax1 + tree[id * 2 + 1].lmax1 >= x) return tree[id * 2].r- tree[id * 2].rmax1 + 1; return query1(id * 2 + 1,x); } void update(int id,int l,int r) { if (tree[id].l == l && tree[id].r == r) { tree[id].mmax = tree[id].lmax = tree[id].rmax = tree[id].r - tree[id].l + 1; tree[id].mmax1 = tree[id].lmax1 = tree[id].rmax1 = tree[id].r - tree[id].l + 1; return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) update(id * 2 + 1,l,r); else if (r <= mid) update(id * 2 ,l,r); else { update(id * 2,l,mid); update(id * 2 + 1,mid + 1,r); } push_up(id); } void diors(int id,int l,int r) { if (tree[id].l == l && tree[id].r == r) { tree[id].mmax = tree[id].lmax = tree[id].rmax = 0; return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) diors(id * 2 + 1,l,r); else if (r <= mid) diors(id * 2,l,r); else { diors(id * 2,l,mid); diors(id * 2 + 1,mid + 1,r); } push_up(id); } void godness(int id,int l,int r) { if (tree[id].l == l && tree[id].r == r) { tree[id].mmax = tree[id].lmax = tree[id].rmax = 0; tree[id].mmax1 = tree[id].lmax1 = tree[id].rmax1 = 0; return; } push_down(id); int mid = (tree[id].l + tree[id].r) / 2; if (l > mid) godness(id * 2 + 1,l,r); else if (r <= mid) godness(id * 2 ,l,r); else { godness(id * 2,l,mid); godness(id * 2 + 1,mid + 1,r); } push_up(id); } int main() { //freopen("sample.txt","r",stdin); int T,kase = 1; scanf("%d",&T); while (T--) { printf("Case %d:\n",kase++); int N,M; scanf("%d%d",&N,&M); build(1,1,N); while (M--) { char op[5]; scanf("%s",op); if (op[0] == ‘D‘) { int x; scanf("%d",&x); int tmp = query(1,x); if (tmp == 0) puts("fly with yourself"); else { diors(1,tmp,tmp + x - 1); printf("%d,let‘s fly\n",tmp); } } else if (op[0] == ‘N‘) { int x; scanf("%d",&x); int tmp = query(1,x); if (tmp != 0) { godness(1,tmp,tmp + x - 1); printf("%d,don‘t put my gezi\n",tmp); continue; } tmp = query1(1,x); if (tmp != 0) { godness(1,tmp,tmp + x - 1); printf("%d,don‘t put my gezi\n",tmp); continue; } printf("wait for me\n"); } else { int l,r; scanf("%d%d",&l,&r); printf("I am the hope of chinese chengxuyuan!!\n"); update(1,l,r); } } } return 0; }
POJ 1177 Picture
线段树扫描线矩形周长并
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 10010; struct node { int l,r; int cnt; int lf,rf; int numseg; int c; bool lcover,rcover; }tree[MAXN * 4]; struct Line { int y; int x1,x2; int f; friend bool operator < (const Line &a,const Line &b) { return a.y < b.y; } }line[MAXN]; int x[MAXN],debug; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].lf = x[l]; tree[id].rf = x[r]; tree[id].cnt = 0; tree[id].numseg = 0; tree[id].c = 0; tree[id].lcover = tree[id].rcover = false; if (l + 1 == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid,r); } void callen(int id) { if (tree[id].c > 0) { tree[id].cnt = tree[id].rf - tree[id].lf; tree[id].numseg = 1; tree[id].lcover = tree[id].rcover = true; return; } if (tree[id].l + 1 == tree[id].r) { tree[id].cnt = 0; tree[id].numseg = 0; tree[id].lcover = tree[id].rcover = false; } else { // printf("%d %d %d\n",tree[id].cnt,tree[id * 2].cnt ,tree[id * 2 + 1].cnt); // printf("%d %d %d %d\n",tree[id * 2].l,tree[id * 2].r,tree[id * 2 + 1].l,tree[id * 2 + 1].r); tree[id].cnt = tree[id * 2].cnt + tree[id * 2 + 1].cnt; tree[id].lcover = tree[id * 2].lcover; tree[id].rcover = tree[id * 2 + 1].rcover; tree[id].numseg = tree[id * 2].numseg + tree[id * 2 + 1].numseg; if (tree[id * 2].rcover && tree[id * 2 + 1].lcover) tree[id].numseg--; } } void update(int id,Line e) { if (tree[id].lf == e.x1 && tree[id].rf == e.x2) { tree[id].c += e.f; // printf("%d %d %d %d %d %d %d\n",debug,tree[id].lf,tree[id].rf,tree[id].cnt,tree[id].c,tree[id].l,tree[id].r); callen(id); return; } if (e.x2 <= tree[id * 2].rf) update(id * 2,e); else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e); else { Line tmp = e; tmp.x2 = tree[id * 2].rf; update(id * 2,tmp); tmp = e; tmp.x1 = tree[id * 2 + 1].lf; update(id * 2 + 1,tmp); } callen(id); } int main() { int n; while (scanf("%d",&n) != EOF) { int cas = 0; int x1,x2,y1,y2; debug = 0; for (int i = 0 ; i < n ; i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); line[cas].x1 = x1; line[cas].x2 = x2; line[cas].y = y1; line[cas].f = 1; x[cas] = x1; cas++; line[cas].x1 = x1; line[cas].x2 = x2; line[cas].y = y2; line[cas].f = -1; x[cas] = x2; cas++; } sort(line,line + cas); sort(x,x + cas); int num = unique(x,x + cas) - x; build(1,0,num - 1); int ret = 0,last = 0; for (int i = 0 ; i < cas - 1 ; i++) { debug++; update(1,line[i]); ret += tree[1].numseg * 2 * (line[i + 1].y - line[i].y); ret += abs(tree[1].cnt - last); // printf("%d %d %d %d\n",line[i].x1,line[i].x2,line[i].y,tree[1].cnt); // printf("%d\n\n",ret); last = tree[1].cnt; } update(1,line[cas - 1]); ret += abs(tree[1].cnt - last); printf("%d\n",ret); } return 0; }
HDU 1542 Atlantis
线段树扫描线举行面积并
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 210; const int INF = 0x3f3f3f3f; int N; struct node { int l,r; double lf,rf; int c; double cnt; }tree[MAXN * 4]; struct Line { double x1,x2; double y; int f; friend bool operator < (const Line &a,const Line &b) { return a.y < b.y; } }line[MAXN]; double x[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].lf = x[l]; tree[id].rf = x[r]; tree[id].c = 0; tree[id].cnt = 0; if (l + 1 == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid,r); } void callen(int id) { if (tree[id].c > 0) { tree[id].cnt = tree[id].rf - tree[id].lf; return; } if (tree[id].l + 1 == tree[id].r) { tree[id].cnt = 0; } else tree[id].cnt = tree[id * 2].cnt + tree[id * 2 + 1].cnt; } void update(int id,Line e) { if (tree[id].lf == e.x1 && tree[id].rf == e.x2) { tree[id].c += e.f; callen(id); return; } if (tree[id * 2].rf >= e.x2) update(id * 2,e); else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e); else { Line tmp = e; tmp.x2 = tree[id * 2].rf; update(id * 2,tmp); tmp = e; tmp.x1 = tree[id * 2 + 1].lf; update(id * 2 + 1,tmp); } callen(id); } int main() { int kase = 1; while (scanf("%d",&N) != EOF) { if (N == 0) break; int cas = 0; for (int i = 0 ; i < N ; i++) { double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[cas].x1 = x1; line[cas].x2 = x2; line[cas].y = y1; line[cas].f = 1; x[cas++] = x1; line[cas].x1 = x1; line[cas].x2 = x2; line[cas].y = y2; line[cas].f = -1; x[cas++] = x2; } sort(x,x + cas); sort(line,line + cas); int num = unique(x ,x + cas) - x; build(1,0,num - 1); double ret = 0; update(1,line[0]); for (int i = 1 ; i < cas ; i++) { ret += (line[i].y - line[i - 1].y) * tree[1].cnt; update(1,line[i]); } printf("Test case #%d\n",kase++); printf("Total explored area: %.2lf\n\n",ret); } return 0; }
HDU 1255 覆盖的面积
矩形被覆盖2次以上的面积并。这个你要理解下这类问题是怎么解决的
首先c只有的被完全区间的时候会更新,区间被覆盖一次的长度表示什么,并不是一定就只覆盖了一次,
详细的看看callen函数。
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 2010; struct node { int l,r; int c; double lf,rf; double cnt,more; }tree[MAXN * 4]; struct Line { double x1,x2; double y; int f; friend bool operator < (const Line &a,const Line &b) { return a.y < b.y; } }line[MAXN]; double x[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].lf = x[l]; tree[id].rf = x[r]; tree[id].cnt = tree[id].more = tree[id].c = 0; if (l + 1 == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid,r); } void callen(int id) { if (tree[id].c >= 2) { tree[id].more = tree[id].rf - tree[id].lf; return; } if (tree[id].c == 1) { tree[id].cnt = tree[id].rf - tree[id].lf; if (tree[id].l + 1 == tree[id].r) tree[id].more = 0; else tree[id].more = tree[id * 2].cnt + tree[id * 2 + 1].cnt; } else { if (tree[id].l == tree[id].r - 1) tree[id].cnt = tree[id].more = 0; else { tree[id].cnt = tree[id * 2].cnt + tree[id * 2 + 1].cnt; tree[id].more = tree[id * 2].more + tree[id * 2 + 1].more; } } } void update(int id,Line e) { if (tree[id].lf == e.x1 && tree[id].rf == e.x2) { tree[id].c += e.f; // printf("%d %d %d %d %d %d %d\n",debug,tree[id].lf,tree[id].rf,tree[id].cnt,tree[id].c,tree[id].l,tree[id].r); callen(id); return; } if (e.x2 <= tree[id * 2].rf) update(id * 2,e); else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e); else { Line tmp = e; tmp.x2 = tree[id * 2].rf; update(id * 2,tmp); tmp = e; tmp.x1 = tree[id * 2 + 1].lf; update(id * 2 + 1,tmp); } callen(id); } int main() { int T; scanf("%d",&T); while (T--) { int N; scanf("%d",&N); int cas = 0; for (int i = 0 ; i < N ; i++) { double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[cas].x1 = x1; line[cas].x2 = x2; line[cas].y = y1; line[cas].f = 1; x[cas++] = x1; line[cas].x1 = x1; line[cas].x2 = x2; line[cas].y = y2; line[cas].f = -1; x[cas++] = x2; } sort(line,line + cas); sort(x,x + cas); int num = unique(x,x + cas) - x; build(1,0,num - 1); update(1,line[0]); double ret = 0; for (int i = 1 ; i < cas ; i++) { ret += (line[i].y - line[i - 1].y) * tree[1].more; update(1,line[i]); } printf("%.2lf\n",ret); } return 0; }
HDU 3642 Get The Treasury
线段树扫面线三维体积并,要求三次的内容。由于Z的绝对值小于500,所以可以枚举z
然后化为2唯来做
如何计算callen 中的once,twice,more是关键,理解很关键
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 2010; const int INF = 0x3f3f3f3f; struct node { int l,r; int lf,rf; int once,twice,more; int c; }tree[MAXN * 4]; int x[MAXN],z[MAXN]; struct Line { int y; int x1,x2; int z1,z2; int f; friend bool operator < (const Line &a,const Line &b) { return a.y < b.y; } }line[MAXN],res[MAXN]; void build(int id,int l,int r) { tree[id].l = l; tree[id].r = r; tree[id].lf = x[l]; tree[id].rf = x[r]; tree[id].c = 0; tree[id].once = tree[id].twice = tree[id].more = 0; if (l + 1 == r) return; int mid = (l + r) / 2; build(id * 2,l,mid); build(id * 2 + 1,mid,r); } void callen(int id) { if (tree[id].c >= 3) { tree[id].more = tree[id].rf - tree[id].lf; tree[id].once = tree[id].twice = 0; return; } else if (tree[id].c == 2) { if (tree[id].l + 1 == tree[id].r) { tree[id].more = 0; tree[id].twice = tree[id].rf - tree[id].lf; tree[id].once = 0; return; } else { tree[id].more = tree[id * 2].once + tree[id * 2].twice + tree[id * 2].more + tree[id * 2 + 1].once + tree[id * 2 + 1].twice + tree[id * 2 + 1].more; tree[id].twice = tree[id].rf - tree[id].lf - tree[id].more; tree[id].once = 0; } } else if (tree[id].c == 1) { if (tree[id].l + 1 == tree[id].r) { tree[id].more = tree[id].twice = 0; tree[id].once = tree[id].rf - tree[id].lf; } else { tree[id].more = tree[id * 2].more + tree[id * 2].twice + tree[id * 2 + 1].more + tree[id * 2 + 1].twice; tree[id].twice = tree[id * 2].once + tree[id * 2 + 1].once; tree[id].once = tree[id].rf - tree[id].lf - tree[id].more - tree[id].twice; } } else { if (tree[id].l == tree[id].r - 1) { tree[id].more = tree[id].twice = tree[id].once = 0; } else { tree[id].more = tree[id * 2].more + tree[id * 2 + 1].more; tree[id].twice = tree[id * 2].twice + tree[id * 2 + 1].twice; tree[id].once = tree[id * 2].once + tree[id * 2 + 1].once; } } } void update(int id,Line e) { if (tree[id].lf == e.x1 && tree[id].rf == e.x2) { tree[id].c += e.f; callen(id); return; } if (tree[id * 2].rf >= e.x2) update(id * 2,e); else if (e.x1 >= tree[id * 2 + 1].lf) update(id * 2 + 1,e); else { Line tmp = e; tmp.x2 = tree[id * 2].rf; update(id * 2,tmp); tmp = e; tmp.x1 = tree[id * 2 + 1].lf; update(id * 2 + 1,tmp); } callen(id); } int main() { int T,kase = 1; scanf("%d",&T); while (T--) { int N; scanf("%d",&N); int cas = 0; for (int i = 0 ; i < N ; i++) { int x1,x2,y1,y2,z1,z2; scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2); line[cas].x1 = x1; line[cas].x2 = x2; line[cas].z1 = z1; line[cas].z2 = z2; line[cas].f = 1; line[cas].y = y1; x[cas] = x1; z[cas++] = z1; line[cas].x1 = x1; line[cas].x2 = x2; line[cas].z1 = z1; line[cas].z2 = z2; line[cas].f = -1; line[cas].y = y2; x[cas] = x2; z[cas++] = z2; } sort(line,line + cas); sort(x,x + cas); sort(z,z + cas); int num = unique(x,x + cas) - x; build(1,0,num - 1); int step = unique(z,z + cas) - z; LL ret = 0,area = 0; for (int i = 0 ; i < step - 1 ; i++) { int tot = 0; for (int j = 0 ; j < cas ; j++) { if (line[j].z1 <= z[i] && line[j].z2 > z[i]) res[tot++] = line[j]; } area = 0; update(1,res[0]); for (int j = 1 ; j < tot ; j++) { area += (LL)(res[j].y - res[j - 1].y) * tree[1].more; update(1,res[j]); } ret += area * (LL)(z[i + 1] - z[i]); } printf("Case %d: %I64d\n",kase++,ret); } return 0; }