Kuangbin 带你飞-线段树专题 题解
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int sum;
}tree[MAXN * ];
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) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
tree[id].sum = tree[id * ].sum + tree[id * + ].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) / ;
if (pos <= mid) update(id * ,pos,val);
else update(id * + ,pos,val);
tree[id].sum = tree[id * ].sum + tree[id * + ].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) / ;
if (l > mid) return query(id * + ,l,r);
else if (r <= mid) return query(id * ,l,r);
else
{
return query(id * ,l,mid) + query(id * + ,mid + ,r);
}
} int main()
{
int T,kase = ;
scanf("%d",&T);
while (T--)
{
int N;
scanf("%d",&N);
for (int i = ; i <= N ; i++) scanf("%d",&src[i]);
build(,,N);
printf("Case %d:\n",kase++);
char op[];
while(scanf("%s",op) != EOF)
{
if (op[] == 'E') break;
if (op[] == 'Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",query(,l,r));
}
if (op[] == 'A')
{
int x,val;
scanf("%d%d",&x,&val);
update(,x,val);
}
if(op[] == 'S')
{
int x,val;
scanf("%d%d",&x,&val);
update(,x,-val);
}
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int val;
}tree[MAXN * ];
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) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
tree[id].val = max(tree[id * ].val,tree[id * + ].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) / ;
if (pos <= mid) update(id * ,pos,val);
else update(id * + ,pos,val);
tree[id].val = max(tree[id * ].val,tree[id * + ].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) / ;
if (l > mid) return query(id * + ,l,r);
else if (r <= mid) return query(id * ,l,r);
else
{
return max(query(id * ,l,mid) ,query(id * + ,mid + ,r));
}
} int main()
{
int N,Q;
while (scanf("%d%d",&N,&Q) != EOF)
{
for (int i = ; i <= N; i++) scanf("%d",&src[i]);
build(,,N);
while (Q--)
{
char op[];
scanf("%s",op);
if (op[] == 'Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",query(,l,r));
}
else
{
int x,val;
scanf("%d%d",&x,&val);
update(,x,val);
}
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
LL lazy,sum;
}tree[MAXN * ];
LL src[MAXN]; void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].lazy = ;
if (l == r)
{
tree[id].sum = src[l];
return;
}
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid +,r);
tree[id].sum = tree[id * ].sum + tree[id * + ].sum;
} void push_down(int id)
{
if (tree[id].lazy == ) return;
tree[id * ].sum += (tree[id * ].r - tree[id * ].l + ) * tree[id].lazy;
tree[id * ].lazy += tree[id].lazy;
tree[id * + ].sum += (tree[id * + ].r - tree[id * + ].l + ) * tree[id].lazy;
tree[id * + ].lazy += tree[id].lazy;
tree[id].lazy = ;
} 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 + );
return;
}
push_down(id);
int mid = (tree[id].r + tree[id].l) / ;
if (l > mid) update(id * + ,l,r,val);
else if (r <= mid) update(id * ,l,r,val);
else
{
update(id * ,l,mid,val);
update(id * + ,mid + ,r,val);
}
tree[id].sum = tree[id * ].sum + tree[id * + ].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) / ;
if (l > mid) return query(id * + ,l,r);
else if (r <= mid) return query(id * ,l,r);
else
{
return query(id * ,l,mid) + query(id * + ,mid + ,r);
}
} int main()
{
int N,Q;
while (scanf("%d%d",&N,&Q) != EOF)
{
for (int i = ; i <= N ; i++) scanf("%I64d",&src[i]);
build(,,N);
char op[];
while (Q--)
{
scanf("%s",op);
if (op[] == 'Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%I64d\n",query(,l,r));
}
else
{
int l,r;
LL val;
scanf("%d%d%I64d",&l,&r,&val);
update(,l,r,val);
}
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
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 * ];
int ori[MAXN * ],newdata[MAXN * ]; void build(int id,int l,int r)
{
tree[id].l = newdata[l];
tree[id].r = newdata[r];
tree[id].val = -;
tree[id].flag = false;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_down(int id)
{
if (tree[id].flag)
{
tree[id * ].flag = tree[id * + ].flag = true;
tree[id * ].val = tree[id * + ].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 * ,l,r,val);
update(id * + ,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] == && tree[id].val != -)
{
ret++;
// printf("%d\n",tree[id].val);
mp[tree[id].val] = ;
}
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
query(id * ,l,mid,ret);
query(id * + ,mid + ,r,ret);
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
mp.clear();
res.clear();
int N;
scanf("%d",&N);
int cas = ;
for (int i = ; 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 + ,ori + + cas);
int leap = ;
ori[] = -;
for (int i = ; i <= cas ; i++)
{
if (ori[i] != ori[i - ])
ori[++leap] = ori[i];
}
cas = ;
newdata[++cas] = ori[];
for (int i = ; i <= leap ; i++)
{
if (ori[i] > ori[i - ] + )
{
newdata[++cas] = ori[i] - ;
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(,,cas);
for (int i = ; i <= N ; i++)
{
update(,src[i].l,src[i].r,src[i].idx);
}
int ret = ;
query(,,cas,ret);
printf("%d\n",ret);
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
bool sta;
int val;
bool flag;
}tree[MAXN * ];
int L; void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].val = ;
tree[id].flag = false;
tree[id].sta = true;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_down(int id)
{
if (tree[id].flag)
{
tree[id * ].val = tree[id * + ].val = tree[id].val;
tree[id * ].flag = true;
tree[id * + ].flag = true;
tree[id].flag = false;
tree[id].sta = true;
tree[id * ].sta = true;
tree[id * + ].sta = true;
}
} void push_up(int id)
{
if (tree[id * ].sta == true && tree[id * + ].sta == true)
{
if (tree[id * ].val == tree[id * + ].val)
{
tree[id].val = tree[id * + ].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) / ;
if (l > mid) update(id * + ,l,r,val);
else if (r <= mid) update(id * ,l,r,val);
else
{
update(id * ,l,mid,val);
update(id * + ,mid + ,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 + );
}
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) return query(id * + ,l,r);
else if (r <= mid) return query(id * ,l,r);
else
{
return query(id * ,l,mid) + query(id * + ,mid + ,r);
}
} int main()
{
int T,kase = ;
scanf("%d",&T);
while (T--)
{
scanf("%d",&L);
build(,,L);
int Q;
scanf("%d",&Q);
while (Q--)
{
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
update(,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(,,L));
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
struct node
{
int l,r,col;
}tree[MAXN * ];
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 = -;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_down(int id)
{
if (tree[id].col != -)
{
tree[id * ].col = tree[id * + ].col = tree[id].col;
tree[id].col = -;
}
} 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) / ;
if (l > mid) update(id * + ,l,r,val);
else if (r <= mid) update(id * ,l,r,val);
else
{
update(id * ,l,mid,val);
update(id * + ,mid + ,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 != -)
{
//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 ) / ;
if (l > mid) query(id * + ,l,r);
else if (r <= mid) query(id * ,l,r);
else
{
query(id * ,l,mid);
query(id * + ,mid + ,r);
}
} int main()
{
while (scanf("%d",&N) != EOF)
{
memset(cnt,,sizeof(cnt));
build(,,);
for (int i = ; i <= N ; i++)
{
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
update(,l + ,r,val);
}
memset(col,-,sizeof(col));
query(,,);
int pre = -;
for (int i = ; i <= ; i++)
{
if (col[i] == -)
{
pre = -;
continue;
}
if (pre != col[i])
{
cnt[col[i]]++;
pre = col[i];
}
}
for (int i = ; i <= ; i++)
{
if (cnt[i]) printf("%d %d\n",i,cnt[i]);
}
puts("");
}
return ;
}
下面是我自己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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
bool flag,sta;
int val;
}tree[MAXN * ];
int N;
int cnt[MAXN]; void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].val = -;
tree[id].flag = false;
tree[id].sta = true;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_down(int id)
{
if (tree[id].flag)
{
tree[id * ].val = tree[id * + ].val = tree[id].val;
tree[id * ].flag = true;
tree[id * + ].flag = true;
tree[id].flag = false;
tree[id].sta = true;
tree[id * ].sta = true;
tree[id * + ].sta = true;
}
} void push_up(int id)
{
if (tree[id * ].sta == true && tree[id * + ].sta == true)
{
if (tree[id * ].val == tree[id * + ].val)
{
tree[id].val = tree[id * + ].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) / ;
if (l > mid) update(id * + ,l,r,val);
else if (r <= mid) update(id * ,l,r,val);
else
{
update(id * ,l,mid,val);
update(id * + ,mid + ,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 != -)
{
cnt[tree[id].val]++;
//a printf("%d\n",tree[id].val);
}
return;
}
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) query(id * + ,l,r);
else if (r <= mid) query(id * ,l,r);
else
{
query(id * ,l,mid);
query(id * + ,mid + ,r);
}
} int main()
{
//freopen("sample.txt","r",stdin);
while (scanf("%d",&N) != EOF)
{
build(,,);
for (int i = ; 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(,l + ,r,val);
}
memset(cnt,,sizeof(cnt));
query(,,);
for (int i = ; i <= ; i++)
{
if (cnt[i] == ) continue;
printf("%d %d\n",i,cnt[i]);
}
puts("");
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
struct node
{
int l,r,MIN,MAX;
}tree[MAXN * ];
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) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
tree[id].MIN = min(tree[id * ].MIN,tree[id * + ].MIN);
tree[id].MAX = max(tree[id * ].MAX,tree[id * + ].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) / ;
if (l > mid) return querymax(id * + ,l,r);
else if (r <= mid) return querymax(id * ,l,r);
else
{
return max(querymax(id * ,l,mid),querymax(id * + ,mid + ,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) / ;
if (l > mid) return querymin(id * + ,l,r);
else if (r <= mid) return querymin(id * ,l,r);
else
{
return min(querymin(id * ,l,mid),querymin(id * + ,mid + ,r));
}
} int main()
{
int Q;
while (scanf("%d%d",&N,&Q) != EOF)
{
for (int i = ; i <= N ; i++) scanf("%d",&src[i]);
build(,,N);
while (Q--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",querymax(,l,r) - querymin(,l,r));
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
LL sum;
bool flag;
}tree[MAXN * ];
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) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
tree[id].sum = tree[id * ].sum + tree[id * + ].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 * );
push_down(id * + );
tree[id].sum = tree[id * + ].sum + tree[id * ].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 + ))
return;
push_down(id);
return;
}
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) update(id * + ,l,r);
else if (r <= mid) update(id * ,l,r);
else
{
update(id * ,l,mid);
update(id * + ,mid + ,r);
}
tree[id].sum = tree[id * ].sum + tree[id * + ].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) / ;
if (l > mid) return query(id * + ,l,r);
else if (r <= mid) return query(id * ,l,r);
else
{
return query(id * ,l,mid) + query(id * + ,mid + ,r);
}
} int main()
{
int N,M,kase = ;
while (scanf("%d",&N) != EOF)
{
for (int i = ; i <= N ; i++) scanf("%I64d",&src[i]);
scanf("%d",&M);
build(,,N);
printf("Case #%d:\n",kase++);
while (M--)
{
int op;
scanf("%d",&op);
if (op == )
{
int l,r;
scanf("%d%d",&l,&r);
if (l > r) swap(l,r);
update(,l,r);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
if (l > r) swap(l,r);
printf("%I64d\n",query(,l,r));
}
}
putchar('\n');
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int leftlen,rightlen,maxlen;
}tree[MAXN * ];
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 + ;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_up(int id)
{
//leftlen;
if (tree[id * ].leftlen == tree[id * ].r - tree[id * ].l + )
{
tree[id].leftlen = tree[id * ].r - tree[id * ].l + + tree[id * + ].leftlen;
}
else tree[id].leftlen = tree[id * ].leftlen;
//right len
if (tree[id * + ].rightlen == tree[id * + ].r - tree[id * + ].l + )
{
tree[id].rightlen = tree[id * + ].r - tree[id * + ].l + + tree[id * ].rightlen;
}
else tree[id].rightlen = tree[id * + ].rightlen;
tree[id].maxlen = max(tree[id * ].maxlen,tree[id * + ].maxlen);
tree[id].maxlen = max(tree[id].maxlen,tree[id * ].rightlen + tree[id * + ].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 = ;
else
tree[id].maxlen = tree[id].leftlen = tree[id].rightlen = ;
return;
}
int mid = (tree[id].l + tree[id].r) / ;
if (pos > mid) update(id * + ,pos,flag);
if (pos <= mid) update(id * ,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 + )
{
return tree[id].maxlen;
}
int mid = (tree[id].l + tree[id].r) / ;
if (pos <= mid)//左半段
{
int tmppos = tree[id * ].r - tree[id * ].rightlen + ;
if (pos >= tmppos) return tree[id * ].rightlen + tree[id * + ].leftlen;
else return query(id * ,pos);
}
else
{
int tmppos = tree[id * + ].l + tree[id * + ].leftlen - ;
if (pos <= tmppos) return tree[id * + ].leftlen + tree[id * ].rightlen;
else return query(id * + ,pos);
}
} int main()
{
//freopen("sample.txt","r",stdin);
int N,Q;
while (scanf("%d%d",&N,&Q) != EOF)
{
build(,,N);
while (!s.empty()) s.pop();
while (Q--)
{
char op[];
scanf("%s",op);
if (op[] == 'D')
{
int pos;
scanf("%d",&pos);
s.push(pos);
update(,pos,true);
}
if (op[] == 'Q')
{
int pos;
scanf("%d",&pos);
printf("%d\n",query(,pos));
}
if (op[] == 'R')
{
if (s.empty()) continue;
int x = s.top();
s.pop();
update(,x,false);
}
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
int L[MAXN],R[MAXN];
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int val;
bool flag;
}tree[MAXN * ]; void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].val = -;
tree[id].flag = false;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_down(int id)
{
if (tree[id].flag)
{
tree[id * ].flag = tree[id * + ].flag = true;
tree[id * ].val = tree[id * + ].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) / ;
if (l > mid) update(id * + ,l,r,val);
else if (r <= mid) update(id * ,l,r,val);
else
{
update(id * ,l,mid,val);
update(id * + ,mid + ,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) / ;
if (pos > mid) return query(id * + ,pos);
else return query(id * ,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 = ; 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 = ;
scanf("%d",&T);
int N,Q;
while(T--)
{
memset(deg,,sizeof(deg));
scanf("%d",&N);
for (int i = ; i <= N ; i++) q[i].clear();
for (int i = ; i < N ; i++)
{
int u,v;
scanf("%d%d",&u,&v);
//q[v].push(u);
q[v].push_back(u);
deg[u]++;
}
build(,,N);
int root = ;
for (int i = ; i <= N ; i++)
{
if (deg[i] == )
{
root = i;
break;
}
}
Index = ;
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[];
scanf("%s",op);
if (op[] == 'C')
{
int x;
scanf("%d",&x);
printf("%d\n",query(,L[x]));
}
else
{
int x,val;
scanf("%d%d",&x,&val);
//printf("%d %d\n",L[x],R[x]);
update(,L[x],R[x],val);
}
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int sum,lazy,lft,rht;
}tree[MAXN * ];
int N,Q; void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].sum = r - l + ;
tree[id].lft = l;
tree[id].rht = r;
tree[id].lazy = ;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_up(int id)
{
if (tree[id].l == tree[id].r) return;
tree[id].sum = tree[id * ].sum + tree[id * + ].sum;
if (tree[id * ].lft != -) tree[id].lft = tree[id * ].lft;
else tree[id].lft = tree[id * + ].lft;
if (tree[id * + ].rht != -) tree[id].rht = tree[id * + ].rht;
else tree[id].rht = tree[id * ].rht;
} void push_down(int id)
{
if (tree[id].l == tree[id].r) return;
if (tree[id].lazy == )
{
tree[id * ].lft = tree[id * ].l;
tree[id * ].rht = tree[id * ].r;
tree[id * ].sum = tree[id * ].r - tree[id * ].l + ;
tree[id * ].lazy = ;
tree[id * + ].lft = tree[id * + ].l;
tree[id * + ].rht = tree[id * + ].r;
tree[id * + ].sum = tree[id * + ].r - tree[id * + ].l + ;
tree[id * + ].lazy = ;
}
if (tree[id].lazy == -)
{
tree[id * ].lft = -;
tree[id * ].rht = -;
tree[id * ].sum = ;
tree[id * ].lazy = -;
tree[id * + ].lft = -;
tree[id * + ].rht = -;
tree[id * + ].sum = ;
tree[id * + ].lazy = -;
}
tree[id].lazy = ;
} void update(int id,int l,int r,int val)
{
if (tree[id].l >= l && tree[id].r <= r)
{
if (val == )
{
if (tree[id].sum == ) return;
tree[id].sum = ;
tree[id].lft = -;
tree[id].rht = -;
tree[id].lazy = -;
return;
}
else if (val == )
{
if (tree[id].r - tree[id].l + == tree[id].sum) return;
tree[id].sum = tree[id].r - tree[id].l + ;
tree[id].lazy = ;
tree[id].lft = tree[id].l;
tree[id].rht = tree[id].r;
return;
}
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) update(id * + ,l,r,val);
else if (r <= mid) update(id * ,l,r,val);
else
{
update(id * ,l,mid,val);
update(id * + ,mid + ,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) / ;
if (l > mid) return getsum(id * + ,l,r);
else if (r <= mid) return getsum(id * ,l,r);
else
{
return getsum(id * ,l,mid) + getsum(id * + ,mid + ,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) / ;
if (l > mid) return queryleft(id * + ,l,r);
else if (r <= mid) return queryleft(id * ,l,r);
else
{
int ret;
ret = queryleft(id * ,l,mid);
if (ret != -) return ret;
ret = queryleft(id * + ,mid + ,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) / ;
if (l > mid) return queryright(id * + ,l,r);
else if (r <= mid) return queryright(id * ,l,r);
else
{
int ret = queryright(id * + ,mid + ,r);
if (ret != -) return ret;
return queryright(id * ,l,mid);
}
} int binseach(int A,int F)
{
int tmp = getsum(,A,N);
if (tmp == ) return - ;
if (tmp < F) return N;
int l = A,r = N;
while (l < r)
{
int mid = (l + r) / ;
int val = getsum(,A,mid);
if (val >= F)
{
r = mid;
}
else l = mid + ;
}
return l;
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&N,&Q);
build(,,N);
while (Q--)
{
int op;
scanf("%d",&op);
if (op == )
{
int A,F;
scanf("%d%d",&A,&F);
A++;
int tmp = binseach(A,F);
if (tmp == -)
{
puts("Can not put any one.");
continue;
}
printf("%d %d\n",queryleft(,A,tmp) - ,queryright(,A,tmp) - );
update(,A,tmp,);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
l++;
r++;
printf("%d\n",r - l + - getsum(,l,r));
update(,l,r,);
}
}
putchar('\n');
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int lmax,rmax,mmax;
int lmax1,rmax1,mmax1;
}tree[MAXN * ]; 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 + ;
tree[id].lmax1 = tree[id].rmax1 = tree[id].mmax1 = r - l + ;
if (l == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void push_up(int id)
{
if (tree[id].r == tree[id].l) return;
tree[id].lmax = tree[id * ].lmax;
if (tree[id * ].lmax == tree[id * ].r - tree[id * ].l + )
tree[id].lmax += tree[id * + ].lmax;
tree[id].rmax = tree[id * + ].rmax;
if (tree[id * + ].rmax == tree[id * + ].r - tree[id * + ].l + )
tree[id].rmax += tree[id * ].rmax;
tree[id].mmax = max(tree[id * ].mmax,tree[id * + ].mmax);
tree[id].mmax = max(tree[id].mmax,tree[id * ].rmax + tree[id * + ].lmax); tree[id].lmax1 = tree[id * ].lmax1;
if (tree[id * ].lmax1 == tree[id * ].r - tree[id * ].l + )
tree[id].lmax1 += tree[id * + ].lmax1;
tree[id].rmax1 = tree[id * + ].rmax1;
if (tree[id * + ].rmax1 == tree[id * + ].r - tree[id * + ].l + )
tree[id].rmax1 += tree[id * ].rmax1;
tree[id].mmax1 = max(tree[id * ].mmax1,tree[id * + ].mmax1);
tree[id].mmax1 = max(tree[id].mmax1,tree[id * ].rmax1 + tree[id * + ].lmax1);
} void push_down(int id)
{
if (tree[id].l == tree[id].r) return;
if (tree[id].mmax == )
{
tree[id * ].lmax = tree[id * ].rmax = tree[id * ].mmax = ;
tree[id * + ].lmax = tree[id * + ].rmax = tree[id * + ].mmax = ;
}
if (tree[id].mmax == tree[id].r - tree[id].l + )
{
tree[id * ].lmax = tree[id * ].rmax = tree[id * ].mmax = tree[id * ].r - tree[id * ].l + ;
tree[id * + ].lmax = tree[id * + ].rmax = tree[id * + ].mmax = tree[id * + ].r - tree[id * + ].l + ;
}
if (tree[id].mmax1 == )
{
tree[id * ].lmax1 = tree[id * ].rmax1 = tree[id * ].mmax1 = ;
tree[id * + ].lmax1 = tree[id * + ].rmax1 = tree[id * + ].mmax1 = ;
}
if (tree[id].mmax1 == tree[id].r - tree[id].l + )
{
tree[id * ].lmax1 = tree[id * ].rmax1 = tree[id * ].mmax1 = tree[id * ].r - tree[id * ].l + ;
tree[id * + ].lmax1 = tree[id * + ].rmax1 = tree[id * + ].mmax1 = tree[id * + ].r - tree[id * + ].l + ;
}
} int query(int id,int x)
{
if (tree[id].mmax < x) return ;
if (tree[id].lmax >= x) return tree[id].l;
if (tree[id * ].mmax >= x) return query(id * ,x);
if (tree[id * ].rmax + tree[id * + ].lmax >= x)
return tree[id * ].r- tree[id * ].rmax + ;
return query(id * + ,x);
} int query1(int id,int x)
{
if (tree[id].mmax1 < x) return ;
if (tree[id].lmax1 >= x) return tree[id].l;
if (tree[id * ].mmax1 >= x) return query1(id * ,x);
if (tree[id * ].rmax1 + tree[id * + ].lmax1 >= x)
return tree[id * ].r- tree[id * ].rmax1 + ;
return query1(id * + ,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 + ;
tree[id].mmax1 = tree[id].lmax1 = tree[id].rmax1 = tree[id].r - tree[id].l + ;
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) update(id * + ,l,r);
else if (r <= mid) update(id * ,l,r);
else
{
update(id * ,l,mid);
update(id * + ,mid + ,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 = ;
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) diors(id * + ,l,r);
else if (r <= mid) diors(id * ,l,r);
else
{
diors(id * ,l,mid);
diors(id * + ,mid + ,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 = ;
tree[id].mmax1 = tree[id].lmax1 = tree[id].rmax1 = ;
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) / ;
if (l > mid) godness(id * + ,l,r);
else if (r <= mid) godness(id * ,l,r);
else
{
godness(id * ,l,mid);
godness(id * + ,mid + ,r);
}
push_up(id);
} int main()
{
//freopen("sample.txt","r",stdin);
int T,kase = ;
scanf("%d",&T);
while (T--)
{
printf("Case %d:\n",kase++);
int N,M;
scanf("%d%d",&N,&M);
build(,,N);
while (M--)
{
char op[];
scanf("%s",op);
if (op[] == 'D')
{
int x;
scanf("%d",&x);
int tmp = query(,x);
if (tmp == ) puts("fly with yourself");
else
{
diors(,tmp,tmp + x - );
printf("%d,let's fly\n",tmp);
}
}
else if (op[] == 'N')
{
int x;
scanf("%d",&x);
int tmp = query(,x);
if (tmp != )
{
godness(,tmp,tmp + x - );
printf("%d,don't put my gezi\n",tmp);
continue;
}
tmp = query1(,x);
if (tmp != )
{
godness(,tmp,tmp + x - );
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(,l,r);
}
}
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
struct node
{
int l,r;
int cnt;
int lf,rf;
int numseg;
int c;
bool lcover,rcover;
}tree[MAXN * ]; 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 = ;
tree[id].numseg = ;
tree[id].c = ;
tree[id].lcover = tree[id].rcover = false;
if (l + == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid,r);
} void callen(int id)
{
if (tree[id].c > )
{
tree[id].cnt = tree[id].rf - tree[id].lf;
tree[id].numseg = ;
tree[id].lcover = tree[id].rcover = true;
return;
}
if (tree[id].l + == tree[id].r)
{
tree[id].cnt = ;
tree[id].numseg = ;
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 * ].cnt + tree[id * + ].cnt;
tree[id].lcover = tree[id * ].lcover;
tree[id].rcover = tree[id * + ].rcover;
tree[id].numseg = tree[id * ].numseg + tree[id * + ].numseg;
if (tree[id * ].rcover && tree[id * + ].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 * ].rf) update(id * ,e);
else if (e.x1 >= tree[id * + ].lf) update(id * + ,e);
else
{
Line tmp = e;
tmp.x2 = tree[id * ].rf;
update(id * ,tmp);
tmp = e;
tmp.x1 = tree[id * + ].lf;
update(id * + ,tmp);
}
callen(id);
} int main()
{
int n;
while (scanf("%d",&n) != EOF)
{
int cas = ;
int x1,x2,y1,y2;
debug = ;
for (int i = ; 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 = ;
x[cas] = x1;
cas++;
line[cas].x1 = x1;
line[cas].x2 = x2;
line[cas].y = y2;
line[cas].f = -;
x[cas] = x2;
cas++;
}
sort(line,line + cas);
sort(x,x + cas);
int num = unique(x,x + cas) - x;
build(,,num - );
int ret = ,last = ;
for (int i = ; i < cas - ; i++)
{
debug++;
update(,line[i]);
ret += tree[].numseg * * (line[i + ].y - line[i].y);
ret += abs(tree[].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[].cnt;
}
update(,line[cas - ]);
ret += abs(tree[].cnt - last);
printf("%d\n",ret);
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
int N; struct node
{
int l,r;
double lf,rf;
int c;
double cnt;
}tree[MAXN * ]; 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 = ;
tree[id].cnt = ;
if (l + == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid,r);
} void callen(int id)
{
if (tree[id].c > )
{
tree[id].cnt = tree[id].rf - tree[id].lf;
return;
}
if (tree[id].l + == tree[id].r)
{
tree[id].cnt = ;
}
else
tree[id].cnt = tree[id * ].cnt + tree[id * + ].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 * ].rf >= e.x2) update(id * ,e);
else if (e.x1 >= tree[id * + ].lf) update(id * + ,e);
else
{
Line tmp = e;
tmp.x2 = tree[id * ].rf;
update(id * ,tmp);
tmp = e;
tmp.x1 = tree[id * + ].lf;
update(id * + ,tmp);
}
callen(id);
} int main()
{
int kase = ;
while (scanf("%d",&N) != EOF)
{
if (N == ) break;
int cas = ;
for (int i = ; 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 = ;
x[cas++] = x1;
line[cas].x1 = x1;
line[cas].x2 = x2;
line[cas].y = y2;
line[cas].f = -;
x[cas++] = x2;
}
sort(x,x + cas);
sort(line,line + cas);
int num = unique(x ,x + cas) - x;
build(,,num - );
double ret = ;
update(,line[]);
for (int i = ; i < cas ; i++)
{
ret += (line[i].y - line[i - ].y) * tree[].cnt;
update(,line[i]);
}
printf("Test case #%d\n",kase++);
printf("Total explored area: %.2lf\n\n",ret);
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
struct node
{
int l,r;
int c;
double lf,rf;
double cnt,more;
}tree[MAXN * ]; 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 = ;
if (l + == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid,r);
} void callen(int id)
{
if (tree[id].c >= )
{
tree[id].more = tree[id].rf - tree[id].lf;
return;
}
if (tree[id].c == )
{
tree[id].cnt = tree[id].rf - tree[id].lf;
if (tree[id].l + == tree[id].r) tree[id].more = ;
else tree[id].more = tree[id * ].cnt + tree[id * + ].cnt;
}
else
{
if (tree[id].l == tree[id].r - )
tree[id].cnt = tree[id].more = ;
else
{
tree[id].cnt = tree[id * ].cnt + tree[id * + ].cnt;
tree[id].more = tree[id * ].more + tree[id * + ].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 * ].rf) update(id * ,e);
else if (e.x1 >= tree[id * + ].lf) update(id * + ,e);
else
{
Line tmp = e;
tmp.x2 = tree[id * ].rf;
update(id * ,tmp);
tmp = e;
tmp.x1 = tree[id * + ].lf;
update(id * + ,tmp);
}
callen(id);
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int N;
scanf("%d",&N);
int cas = ;
for (int i = ; 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 = ;
x[cas++] = x1;
line[cas].x1 = x1;
line[cas].x2 = x2;
line[cas].y = y2;
line[cas].f = -;
x[cas++] = x2;
}
sort(line,line + cas);
sort(x,x + cas);
int num = unique(x,x + cas) - x;
build(,,num - );
update(,line[]);
double ret = ;
for (int i = ; i < cas ; i++)
{
ret += (line[i].y - line[i - ].y) * tree[].more;
update(,line[i]);
}
printf("%.2lf\n",ret);
}
return ;
}
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 == ? b : gcd(b, a % b);}
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct node
{
int l,r;
int lf,rf;
int once,twice,more;
int c;
}tree[MAXN * ];
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 = ;
tree[id].once = tree[id].twice = tree[id].more = ;
if (l + == r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid,r);
} void callen(int id)
{
if (tree[id].c >= )
{
tree[id].more = tree[id].rf - tree[id].lf;
tree[id].once = tree[id].twice = ;
return;
}
else if (tree[id].c == )
{
if (tree[id].l + == tree[id].r)
{
tree[id].more = ;
tree[id].twice = tree[id].rf - tree[id].lf;
tree[id].once = ;
return;
}
else
{
tree[id].more = tree[id * ].once + tree[id * ].twice + tree[id * ].more
+ tree[id * + ].once + tree[id * + ].twice + tree[id * + ].more;
tree[id].twice = tree[id].rf - tree[id].lf - tree[id].more;
tree[id].once = ;
}
}
else if (tree[id].c == )
{
if (tree[id].l + == tree[id].r)
{
tree[id].more = tree[id].twice = ;
tree[id].once = tree[id].rf - tree[id].lf;
}
else
{
tree[id].more = tree[id * ].more + tree[id * ].twice
+ tree[id * + ].more + tree[id * + ].twice;
tree[id].twice = tree[id * ].once + tree[id * + ].once;
tree[id].once = tree[id].rf - tree[id].lf - tree[id].more - tree[id].twice;
}
}
else
{
if (tree[id].l == tree[id].r - )
{
tree[id].more = tree[id].twice = tree[id].once = ;
}
else
{
tree[id].more = tree[id * ].more + tree[id * + ].more;
tree[id].twice = tree[id * ].twice + tree[id * + ].twice;
tree[id].once = tree[id * ].once + tree[id * + ].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 * ].rf >= e.x2) update(id * ,e);
else if (e.x1 >= tree[id * + ].lf) update(id * + ,e);
else
{
Line tmp = e;
tmp.x2 = tree[id * ].rf;
update(id * ,tmp);
tmp = e;
tmp.x1 = tree[id * + ].lf;
update(id * + ,tmp);
}
callen(id);
}
int main()
{
int T,kase = ;
scanf("%d",&T);
while (T--)
{
int N;
scanf("%d",&N);
int cas = ;
for (int i = ; 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 = ;
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 = -;
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(,,num - );
int step = unique(z,z + cas) - z;
LL ret = ,area = ;
for (int i = ; i < step - ; i++)
{
int tot = ;
for (int j = ; j < cas ; j++)
{
if (line[j].z1 <= z[i] && line[j].z2 > z[i])
res[tot++] = line[j];
}
area = ;
update(,res[]);
for (int j = ; j < tot ; j++)
{
area += (LL)(res[j].y - res[j - ].y) * tree[].more;
update(,res[j]);
}
ret += area * (LL)(z[i + ] - z[i]);
}
printf("Case %d: %I64d\n",kase++,ret);
}
return ;
}
离散处理题目。求区间内不同数字的和,和不同数字的个数
Uvalive 5970 An Average Game
离散右端点排序每次标记上一次出现的位置
#include<bits/stdc++.h>
using namespace std;
const int MAXN = ;
#define LL long long
struct node {
int l,r;
int idx;
friend bool operator < (const node &a,const node &b) {
if (a.r == b.r) return a.l < b.l;
return a.r < b.r;
}
}src[MAXN];
int N,Q;
LL A[MAXN];
pair<LL,LL>ans[MAXN ]; struct treenode {
int l,r;
int sum;
}tree[MAXN * ]; void build(int id,int l,int r) {
tree[id].l = l;
tree[id].r = r;
tree[id].sum = ;
if (l >= r) return;
int mid = (l + r) / ;
build(id * ,l,mid);
build(id * + ,mid + ,r);
} void update(int id,int pos,bool flag) {
if (tree[id].l == pos && tree[id].r == pos) {
if (flag) tree[id].sum = ;
else tree[id].sum = ;
return;
}
int mid = (tree[id].l + tree[id].r) / ;
if (pos <= mid) update(id * ,pos,flag);
else update(id * + ,pos,flag);
tree[id].sum = tree[id * ].sum + tree[id * + ].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) / ;
if (r <= mid) return query(id * ,l,r);
else if (l > mid) return query(id * + ,l,r);
else {
return query(id * ,l,mid) + query(id * + ,mid + ,r);
}
} struct IntervalTree
{
LL sum[MAXN * ];
void build(){memset(sum,,sizeof(sum));}
void update(int o,int l,int r,int pos,int val)
{
if(l == r)
{
sum[o] += val;
return;
}
int mid = (l + r) >> ;
if(pos <= mid)update(o << ,l,mid,pos,val);
else update(o<< | ,mid + ,r,pos,val);
sum[o]=sum[o << ]+sum[o << |];
}
LL query(int o,int l,int r,int q1,int q2)
{
if(q1 <= l && r <= q2)return sum[o];
int mid=(l + r)>>;
LL ans=;
if(q1 <= mid)ans += query(o << ,l,mid,q1,q2);
if(q2 > mid)ans += query(o << | ,mid + ,r,q1,q2);
return ans;
}
}Tree; map<int,int>vis;
int main() {
int T,kase = ;
cin >> T;
while (T--) {
cin >> N;
for (int i = ; i <= N ; i++) cin >> A[i];
cin >> Q;
for (int i = ; i <= Q ; i++) { cin >> src[i].l >> src[i].r; if (src[i].l > src[i].r) swap(src[i].l,src[i].r); }
for (int i = ; i <= Q ; i++) src[i].idx = i;
vis.clear();
sort(src + ,src + + Q);
build(,,N);
int curpos = ;
for (int i = ; i <= Q ; i++) {
while (curpos <= N && curpos <= src[i].r) {
if (vis[A[curpos]]) update(,vis[A[curpos]],true);
update(,curpos,false);
vis[A[curpos]] = curpos;
curpos++;
}
ans[src[i].idx].first = (LL)query(,src[i].l,src[i].r);
} Tree.build();
vis.clear();
int cur = ;
for(int i = ; i <= Q ; i++)
{
for(; cur <= N && cur <= src[i].r ; cur++)
{
if(vis[A[cur]])Tree.update(,,N,vis[A[cur]],-A[cur]);
Tree.update(,,N,cur,A[cur]);
vis[A[cur]] = cur;
}
ans[src[i].idx].second = Tree.query(,,N,src[i].l,src[i].r);
}
// for (int i = 1 ; i <= Q ; i++) cout << ans[i].first << " " << ans[i].second << endl;
printf("Case %d:\n",kase++);
for (int i = ; i <= Q ; i++) printf("%.6lf\n",(1.0 * ans[i].second) / (1.0 * ans[i].first));
}
return ;
}
Kuangbin 带你飞-线段树专题 题解的更多相关文章
- Kuangbin 带你飞-基础计算几何专题 题解
专题基本全都是模版应用.贴一下模版 平面最近点对 const double INF = 1e16; ; struct Point { int x,y; int type; }; double dist ...
- kuangbin带你飞 并查集 题解
做这套题之前一直以为并查集是很简单的数据结构. 做了才发现自己理解太不深刻.只看重片面的合并集合.. 重要的时发现每个集合的点与这个根的关系,这个关系可以做太多事情了. 题解: POJ 2236 Wi ...
- 【kuangbin带你飞】 MST专题
唉,被班级合唱和复变考试搞得心力交瘁.新算法学不进去,更新下吧 A - Til the Cows Come Home The Head Elder of the tropical island of ...
- vj线段树专题
vj线段树专题题解 单点更新模板 void build(int x,int l,int r){//sum[x]控制l-r区域 if(l==r){Sum[x]=num[l];return ;} int ...
- 「kuangbin带你飞」专题十七 AC自动机
layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...
- [kuangbin带你飞]专题1-23题目清单总结
[kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...
- 「kuangbin带你飞」专题二十 斜率DP
layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...
- 「kuangbin带你飞」专题二十二 区间DP
layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...
- 「kuangbin带你飞」专题十九 矩阵
layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...
随机推荐
- 3、shader深度测试(Cull、ZWrite 、ZTest )
剔除和深度测试是渲染法线中的一个流程 Cull:默认情况下,Unity中给的所有Shader都是单面的,它都把反面的渲染给关闭掉了,如果你在开发的过程中需要使用到双面,只要把cull关闭(off)即可 ...
- tp5 项目实战 初级 文字步骤
项目实战 环境搭建 新建模块 admin 新建文件夹 controller model view View 中新建 user index 相关样式 js 图片 放入publ ...
- 孤荷凌寒自学python第六十九天学习并实践beautifulsoup对象用法2
孤荷凌寒自学python第六十九天学习并实践beautifulsoup对象用法2 (完整学习过程屏幕记录视频地址在文末) 今天继续学习beautifulsoup对象的属性与方法等内容. 一.今天进一步 ...
- 问题 E: 完数与盈数
问题 E: 完数与盈数 时间限制: 1 Sec 内存限制: 32 MB提交: 73 解决: 69[提交][状态][讨论版][命题人:外部导入] 题目描述 一个数如果恰好等于它的各因子(该数本身除外 ...
- Linux服务架设篇--ping命令
工作原理: 向远程机发送包含一定字节数的ICMP数据包,如果能收到对方的回复的数据包,就表明网络是相通的,而且根据两个数据包的时间差,还可以知道相互之间网络链接的速度. 注意: 有些远程主机由于某种原 ...
- Leetcode 672.灯泡开关II
灯泡开关II 现有一个房间,墙上挂有 n 只已经打开的灯泡和 4 个按钮.在进行了 m 次未知操作后,你需要返回这 n 只灯泡可能有多少种不同的状态. 假设这 n 只灯泡被编号为 [1, 2, 3 . ...
- HDU 4587 TWO NODES(割点)(2013 ACM-ICPC南京赛区全国邀请赛)
Description Suppose that G is an undirected graph, and the value of stab is defined as follows: Amon ...
- import方法引入模块详解
在python用import或者from...import或者from...import...as...来导入相应的模块,作用和使用方法与C语言的include头文件类似.其实就是引入某些成熟的函数库 ...
- 面试题中经常遇到的SQL题:删除重复数据,保留其中一条
如题,解决思路如下: 1.首先我们需要找出拥有重复数据的记录 ---以name字段分组 select Name,COUNT(Name) as [count] from Permission group ...
- 《Effective STL》学习笔记
http://www.cnblogs.com/arthurliu/archive/2011/08/07/2108386.html 作者:咆哮的马甲 出处:http://www.cnblogs.com/ ...