线段树
1 //hdu 5726 2 //区间gcd 3 #include <iostream> 4 #include <cstdio> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <utility> 9 #include <vector> 10 #include <map> 11 #include <queue> 12 #include <stack> 13 #include <cstdlib> 14 typedef long long ll; 15 #define lowbit(x) (x&(-x)) 16 #define ls l,m,rt<<1 17 #define rs m+1,r,rt<<1|1 18 using namespace std; 19 int t,n,q; 20 const int N=1e5+9; 21 int a[N],tree[N<<2]; 22 map<int,ll>dp[N],ans; 23 void init() 24 { 25 for(int i=0;i<=n;i++) dp[i].clear(); 26 ans.clear();//多组输入,要清空。 27 for(int i=1;i<=n;i++) 28 { 29 dp[i][a[i]]++; 30 ans[a[i]]++; 31 for(auto it=dp[i-1].begin();it!=dp[i-1].end();it++){ 32 int p=it->first; 33 ll q=it->second; 34 int w=__gcd(a[i],p); 35 dp[i][w]+=q;//包含第i个数的gcd为w的区间个数。 36 ans[w]+=q;//gcd为w的区间个数 37 } 38 } 39 } 40 void ph(int rt) 41 { 42 tree[rt]=__gcd(tree[rt<<1],tree[rt<<1|1]); 43 } 44 void build(int l=1,int r=n,int rt=1) 45 { 46 if(l==r) 47 { 48 tree[rt]=a[l]; 49 return ; 50 } 51 int m=(r+l)>>1; 52 build(ls);build(rs); 53 ph(rt); 54 } 55 int query(int l1,int r1,int l=1,int r=n,int rt=1) 56 { 57 if(l1<=l&&r1>=r) { 58 return tree[rt]; 59 } 60 int m=(r+l)>>1; 61 if(l1>m) return query(l1,r1,rs);//l1==m时左右都要查询。 62 if(r1<=m) return query(l1,r1,ls); 63 return __gcd(query(l1,r1,ls),query(l1,r1,rs)); 64 } 65 int main() 66 { 67 scanf("%d",&t); 68 for(int i=1;i<=t;i++) 69 { 70 printf("Case #%d:\n",i); 71 scanf("%d",&n); 72 for(int i=1;i<=n;i++) 73 { 74 scanf("%d",&a[i]); 75 } 76 init(); 77 build(); 78 scanf("%d",&q); 79 int x,y; 80 while(q--) 81 { 82 scanf("%d%d",&x,&y); 83 int ret=query(x,y); 84 printf("%d %lld\n",ret,ans[ret]); 85 } 86 } 87 return 0; 88 }
1 /hdu 1754
// 单点更新,区间极值
2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <utility> 8 #include <vector> 9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <cstdlib> 13 #include <cmath> 14 typedef long long ll; 15 #define lowbit(x) (x&(-x)) 16 #define ls l,m,rt<<1 17 #define rs m+1,r,rt<<1|1 18 using namespace std; 19 #define pi acos(-1) 20 const double e = 2.71828182845; 21 int n,m; 22 const int N=2e5+9; 23 int tree[N<<2],a[N]; 24 char s[2]; 25 void ph(int rt){ 26 tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); 27 } 28 void build(int l=1,int r=n,int rt=1){ 29 if(l==r){ 30 tree[rt]=a[l]; 31 return ; 32 } 33 int m=(l+r)>>1; 34 build(ls);build(rs); 35 ph(rt); 36 } 37 int query(int l1,int r1,int l=1,int r=n,int rt=1){ 38 if(l1<=l&&r1>=r){ 39 return tree[rt]; 40 } 41 int m=(l+r)>>1; 42 if(r1<=m){ 43 return query(l1,r1,ls); 44 } 45 if(l1>m){//l1==m时,两侧都要查询。 46 return query(l1,r1,rs); 47 } 48 return max(query(l1,r1,ls),query(l1,r1,rs)); 49 } 50 void update(int pos,int num,int l=1,int r=n,int rt=1) 51 { 52 if(l==r&&l==pos){ 53 tree[rt]=num; 54 return ; 55 } 56 int m=(l+r)>>1; 57 if(pos<=m) update(pos,num,ls);//pos==m还是要在左边更新 58 else update(pos,num,rs); 59 ph(rt); 60 } 61 int main() 62 { 63 while(~scanf("%d%d",&n,&m)){ 64 memset(a,0,sizeof(a)); 65 memset(tree,0,sizeof(tree));//每次要清空 66 for(int i=1;i<=n;i++) 67 { 68 scanf("%d",&a[i]); 69 } 70 build(); 71 int x,y; 72 while(m--) 73 { 74 scanf("%s%d%d",s,&x,&y); 75 if(s[0]=='Q'){ 76 printf("%d\n",query(x,y)); 77 } 78 else{ 79 update(x,y); 80 } 81 } 82 } 83 return 0; 84 }
YJJ's Salesman hdu 6447
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1212 Accepted Submission(s): 425
Problem Description
YJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.
One day, he is going to travel from city A to southeastern city B. Let us assume that A is (0,0) on the rectangle map and B (109,109). YJJ is so busy so he never turn back or go twice the same way, he will only move to east, south or southeast, which means, if YJJ is at (x,y) now (0≤x≤109,0≤y≤109), he will only forward to (x+1,y), (x,y+1) or (x+1,y+1).
On the rectangle map from (0,0) to (109,109), there are several villages scattering on the map. Villagers will do business deals with salesmen from northwestern, but not northern or western. In mathematical language, this means when there is a village k on (xk,yk) (1≤xk≤109,1≤yk≤109), only the one who was from (xk−1,yk−1) to (xk,yk) will be able to earn vk dollars.(YJJ may get different number of dollars from different village.)
YJJ has no time to plan the path, can you help him to find maximum of dollars YJJ can get.
One day, he is going to travel from city A to southeastern city B. Let us assume that A is (0,0) on the rectangle map and B (109,109). YJJ is so busy so he never turn back or go twice the same way, he will only move to east, south or southeast, which means, if YJJ is at (x,y) now (0≤x≤109,0≤y≤109), he will only forward to (x+1,y), (x,y+1) or (x+1,y+1).
On the rectangle map from (0,0) to (109,109), there are several villages scattering on the map. Villagers will do business deals with salesmen from northwestern, but not northern or western. In mathematical language, this means when there is a village k on (xk,yk) (1≤xk≤109,1≤yk≤109), only the one who was from (xk−1,yk−1) to (xk,yk) will be able to earn vk dollars.(YJJ may get different number of dollars from different village.)
YJJ has no time to plan the path, can you help him to find maximum of dollars YJJ can get.
Input
The first line of the input contains an integer T (1≤T≤10),which is the number of test cases.
In each case, the first line of the input contains an integer N (1≤N≤105).The following N lines, the k-th line contains 3 integers, xk,yk,vk (0≤vk≤103), which indicate that there is a village on (xk,yk) and he can get vk dollars in that village.
The positions of each village is distinct.
In each case, the first line of the input contains an integer N (1≤N≤105).The following N lines, the k-th line contains 3 integers, xk,yk,vk (0≤vk≤103), which indicate that there is a village on (xk,yk) and he can get vk dollars in that village.
The positions of each village is distinct.
Output
The maximum of dollars YJJ can get.
Sample Input
1
3
1 1 1
1 2 2
3 3 1
Sample Output
3
Source
单点更新,区间极值
int t,n,tree[N<<2]; struct M{ int x,y,ux,uy,w; }mm[N]; void ph(int rt) { tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); } void build(int l=1,int r=n,int rt=1) { if(l==r) { tree[rt]=0; return ; } int mid=(r+l)>>1; build(ls);build(rs); ph(rt); } void update(int l1,int num,int l=1,int r=n,int rt=1) { if(l==r&&l==l1){ tree[rt]=num; return ; } int mid=(r+l)>>1; if(l1<=mid) update(l1,num,ls); else update(l1,num,rs); ph(rt); } int query(int l1,int r1,int l=1,int r=n,int rt=1) { if(l1<=l&&r1>=r) { return tree[rt]; } int mid=(r+l)>>1; if(r1<=mid)return query(l1,r1,ls); if(l1>mid) return query(l1,r1,rs); return max(query(l1,r1,ls),query(l1,r1,rs)); } bool cmp1(M a,M b) { return a.x<b.x; } bool cmp2(M a,M b) { return a.y<b.y; } bool cmp3(M a,M b) { if(a.x!=b.x) return a.x<b.x; return a.y>b.y; //因为从列的角度考虑最大值,行的话仅需要从左到右 //但是列要从小到上(大到小) } int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); build(); gep(i,1,n){ scanf("%d%d%d",&mm[i].x,&mm[i].y,&mm[i].w); } sort(mm+1,mm+1+n,cmp1); int X=1; gep(i,1,n){ mm[i].ux=X; if(mm[i+1].x!=mm[i].x) X++; } sort(mm+1,mm+1+n,cmp2); int Y=1; gep(i,1,n){ mm[i].uy=Y; if(mm[i+1].y!=mm[i].y) Y++; } //以上就是离散化 sort(mm+1,mm+1+n,cmp3); gep(i,1,n ){ if(mm[i].uy ==1) update(mm[i].uy,mm[i].w); else{ int maxx=query(1,mm[i].uy-1)+mm[i].w;//从1~mm[i].y-1列的最大值再加上 update(mm[i].uy,maxx); } } printf("%d\n",query(1,n)); } return 0; }
1 // // 区间查询,区间更新。 2 // hdu 1698 3 #include <iostream> 4 #include <cstdio> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <utility> 9 #include <vector> 10 #include <map> 11 #include <queue> 12 #include <stack> 13 #include <cstdlib> 14 typedef long long ll; 15 #define lowbit(x) (x&(-x)) 16 #define ls l,m,rt<<1 17 #define rs m+1,r,rt<<1|1 18 using namespace std; 19 const int N=1e5+9; 20 int n,q; 21 ll a[N],tree[N<<2],add[N<<2]; 22 void ph(int rt) 23 { 24 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 25 } 26 void phh(int rt,int len) 27 { 28 if(add[rt]) 29 { 30 add[rt<<1]=add[rt]; 31 add[rt<<1|1]=add[rt]; 32 tree[rt<<1]=add[rt]*(len-(len>>1)); 33 tree[rt<<1|1]=add[rt]*(len>>1); 34 add[rt]=0;//消除延迟标记 35 } 36 } 37 void build(int l=1,int r=n,int rt=1) 38 { 39 if(l==r) 40 { 41 tree[rt]=1; 42 return ; 43 } 44 int m=(r+l)>>1; 45 build(ls);build(rs); 46 ph(rt);//别忘了 47 } 48 void update(int l1,int r1,ll num,int l=1,int r=n,int rt=1) 49 { 50 if(l1<=l&&r1>=r){ 51 add[rt]=num; 52 tree[rt]=num*(r-l+1); 53 return ; 54 } 55 phh(rt,r-l+1); 56 int m=(r+l)>>1; 57 if(l1<=m) update(l1,r1,num,ls); 58 if(r1>m) update(l1,r1,num,rs); 59 ph(rt); 60 } 61 ll query(int l1,int r1,int l=1,int r=n,int rt=1) 62 { 63 if(l1<=l&&r1>=r) 64 { 65 return tree[rt]; 66 } 67 phh(rt,r-l+1);//不加这句可以求1到n,但是不能求其他的和 68 ll ans=0; 69 int m=(r+l)>>1; 70 if(l1<=m) ans+=query(l1,r1,ls); 71 if(r1>m) ans+=query(l1,r1,rs); 72 return ans; 73 } 74 int main() 75 { 76 int t; 77 scanf("%d",&t); 78 for(int i=1;i<=t;i++){ 79 memset(add,0,sizeof(add)); 80 memset(tree,0,sizeof(tree)); 81 scanf("%d%d",&n,&q); 82 build(); 83 int x,y,z; 84 while(q--) 85 { 86 scanf("%d%d%d",&x,&y,&z); 87 update(x,y,z); 88 } 89 printf("Case %d: The total value of the hook is %d.\n",i,query(1,n)); 90 } 91 return 0; 92 }
1 // hdu 1166 2 // 单点更新,区间求和 3 #include <iostream> 4 #include <algorithm> 5 #include <cstring> 6 #include <cstdio> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #include <cstdlib> 11 #include <iomanip> 12 #include <cmath> 13 #include <cassert> 14 #include <ctime> 15 #include <cstdlib> 16 #include <map> 17 #include <set> 18 using namespace std; 19 #define ll long long 20 #define lowbit(x) (x&(-x)) 21 #define max(x,y) (x>=y?x:y) 22 #define min(x,y) (x<=y?x:y) 23 #define MAX 100000000000000000 24 #define MOD 1000000007 25 #define pi acos(-1.0) 26 #define ei exp(1) 27 #define PI 3.1415926535897932384626433832 28 #define ios() ios::sync_with_stdio(true) 29 #define inf 1044266558 30 #define mem(a) (memset(a,0,sizeof(a))) 31 #define ls l,m,rt<<1 32 #define rs m+1,r,rt<<1|1 33 //typedef unsigned long long ll; 34 map<int,ll>mp; 35 const int N=5e4+9; 36 char s[10]; 37 int sum[N<<2],aa[N<<2],t,n; 38 void ph(int rt) 39 { 40 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 41 } 42 void build(int l,int r,int rt) 43 { 44 if(l==r) 45 { 46 //scanf("%d",&sum[rt]); 47 sum[rt] = aa[l]; 48 return ; 49 } 50 int m=(l+r)>>1; 51 build(ls); 52 build(rs); 53 ph(rt); 54 } 55 void up(int x,int add,int l,int r,int rt) 56 { 57 if(l==r) 58 { 59 sum[rt]+=add; 60 return ; 61 } 62 int m=(l+r)>>1; 63 if(x<=m) 64 { 65 up(x,add,ls); 66 } 67 else 68 { 69 up(x,add,rs); 70 } 71 ph(rt); 72 } 73 int qu(int l0,int r0,int l,int r,int rt) 74 { // m 是左区间的 75 if(l0<=l&&r0>=r) 76 { 77 return sum[rt]; 78 } 79 int m=(l+r)>>1; 80 int ret=0; 81 if(l0<=m) 82 { 83 ret+=qu(l0,r0,ls); 84 } 85 if(r0>m) 86 { 87 ret+=qu(l0,r0,rs);//r0==m加左区间 88 } 89 //ph(rt); 90 return ret; 91 } 92 int main() 93 { 94 scanf("%d",&t); 95 for(int i=1;i<=t;i++) 96 { 97 scanf("%d",&n); 98 mem(sum); 99 mem(aa); 100 for(int i=1;i<=n;i++) scanf("%lld",&aa[i]); 101 build(1,n,1); 102 printf("Case %d:\n",i); 103 while(scanf("%s",s)) 104 { 105 int a,b; 106 if(s[0]=='E') 107 { 108 break; 109 } 110 scanf("%d %d",&a,&b); 111 if(s[0]=='A') 112 { 113 114 up(a,b,1,n,1); 115 } 116 else if(s[0]=='Q') 117 { 118 printf("%d\n",qu(a,b,1,n,1)); 119 120 } 121 else 122 { 123 up(a,-b,1,n,1); 124 } 125 } 126 } 127 return 0; 128 }
1 // hdu 2795
// 单点修改,单点查询
2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <utility> 8 #include <vector> 9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <cstdlib> 13 typedef long long ll; 14 #define lowbit(x) (x&(-x)) 15 #define ls l,m,rt<<1 16 #define rs m+1,r,rt<<1|1 17 using namespace std; 18 int h,w,n; 19 const int N=2e5+9; 20 int tree[N<<2];//管辖的区间内空余长度的最大值 21 void ph(int rt) 22 { 23 tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); 24 } 25 void build(int l=1,int r=h,int rt=1) 26 { 27 tree[rt]=w; 28 if(l==r) 29 return ; 30 int m=(r+l)>>1; 31 build(ls);build(rs); 32 //初始状态都是w,因此不再更新 33 } 34 int query(int val ,int l=1,int r=h,int rt=1){ 35 if(l==r) { 36 tree[rt]-=val;//最上最左 37 return l; 38 } 39 int m=(r+l)>>1; 40 int ret; 41 ret=(tree[rt<<1]>=val)?query(val,ls):query(val,rs); 42 ph(rt); 43 return ret; 44 } 45 int main() 46 { 47 while(~scanf("%d%d%d",&h,&w,&n)) 48 { 49 if(h>n) h=n;//一行一个最多n行 50 build(); 51 int val; 52 for(int i=0;i<n;i++) 53 { 54 scanf("%d",&val); 55 if(tree[1]<val) printf("-1\n");//无法贴 56 else{ 57 printf("%d\n",query(val)); 58 } 59 } 60 } 61 return 0; 62 }
1 // 牛客小白月赛5 2 // I 区间 (interval) 3 // 区间修改,区间加减,再区间求和 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 #include <string> 9 #include <algorithm> 10 #include <utility> 11 #include <vector> 12 #include <map> 13 #include <queue> 14 #include <stack> 15 #include <cstdlib> 16 typedef long long ll; 17 #define lowbit(x) (x&(-x)) 18 #define ls l,m,rt<<1 19 #define rs m+1,r,rt<<1|1 20 using namespace std; 21 const int N=1e6+9; 22 int n,q; 23 ll a[N],tree[N<<2],add[N<<2]; 24 void ph(int rt) 25 { 26 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 27 } 28 void phh(int rt,int len) 29 { 30 if(add[rt]) 31 { //都是累加的 32 add[rt<<1]+=add[rt]; 33 add[rt<<1|1]+=add[rt]; 34 tree[rt<<1]+=add[rt]*(len-(len>>1)); 35 tree[rt<<1|1]+=add[rt]*(len>>1); 36 add[rt]=0;//消除延迟标记 37 } 38 } 39 void build(int l=1,int r=n,int rt=1) 40 { 41 if(l==r) 42 { 43 tree[rt]=a[l]; 44 return ; 45 } 46 int m=(r+l)>>1; 47 build(ls);build(rs); 48 ph(rt);//别忘了 49 } 50 void update(int l1,int r1,ll num,int l=1,int r=n,int rt=1) 51 { 52 if(l1<=l&&r1>=r){ 53 add[rt]+=num;//注意这些也都是累加的 54 tree[rt]+=num*(r-l+1);//隐式类型朱转换如:1.0*整型为double 55 return ; 56 } 57 phh(rt,r-l+1); 58 int m=(r+l)>>1; 59 if(l1<=m) update(l1,r1,num,ls); 60 if(r1>m) update(l1,r1,num,rs); 61 ph(rt); 62 } 63 ll query(int l1,int r1,int l=1,int r=n,int rt=1) 64 { 65 if(l1<=l&&r1>=r) 66 { 67 return tree[rt]; 68 } 69 phh(rt,r-l+1);//不加这句可以求1到n,但是不能求其他的和 70 ll ans=0; 71 int m=(r+l)>>1; 72 if(l1<=m) ans+=query(l1,r1,ls); 73 if(r1>m) ans+=query(l1,r1,rs); 74 return ans; 75 } 76 int main() 77 { 78 scanf("%d%d",&n,&q); 79 for(int i=1;i<=n;i++) 80 { 81 scanf("%lld",&a[i]); 82 } 83 build(); 84 int a,b,c; 85 ll d; 86 while(q--){ 87 scanf("%d%d%d%lld",&a,&b,&c,&d); 88 if(a==1){ 89 update(b,c,-d); 90 } 91 else{ 92 update(b,c,d); 93 } 94 } 95 int l,r; 96 scanf("%d%d",&l,&r); 97 printf("%lld\n",query(l,r)); 98 }
1 // zoj 1610 2 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include <utility> 10 #include <vector> 11 #include <map> 12 #include <queue> 13 #include <stack> 14 #include <cstdlib> 15 typedef long long ll; 16 #define lowbit(x) (x&(-x)) 17 #define ls l,m,rt<<1 18 #define rs m+1,r,rt<<1|1 19 using namespace std; 20 const int N=8100; 21 int add[N<<2],num[N<<2]; 22 int n,last; 23 void ph(int rt) 24 { 25 if(add[rt]!=-1){ 26 add[rt<<1]=add[rt]; 27 add[rt<<1|1]=add[rt]; 28 add[rt]=-1; 29 } 30 } 31 void update(int l1,int r1,int x,int l=1,int r=8000,int rt=1) 32 { 33 if(l1<=l&&r1>=r){ 34 add[rt]=x; 35 return ; 36 } 37 ph(rt); 38 int m=(r+l)>>1; 39 if(l1<=m) update(l1,r1,x,ls); 40 if(r1>m) update(l1,r1,x,rs); 41 } 42 void query(int l=1,int r=8000,int rt=1) 43 { 44 if(l==r){ 45 if(add[rt]!=-1&&add[rt]!=last){//连着的区间是一样的 46 47 num[add[rt]]++; 48 } 49 last=add[rt];//查询其他的,比较的是右边的。 50 return ; 51 } 52 ph(rt); 53 int m=(r+l)>>1; 54 query(ls);query(rs);//整体查询 55 } 56 int main() 57 { int a,b,c; 58 59 while(~scanf("%d",&n)){//直接拿8000建树,因为输入的n组数据的 60 //区间范围不明确。 61 memset(add,-1,sizeof(add)); 62 memset(num,0,sizeof(num)); 63 //只需要上面的初始化,不再需要build(). 64 for(int i=1;i<=n;i++) 65 { 66 scanf("%d%d%d",&a,&b,&c); 67 update(a+1,b,c);//看成更新点,不连续。 68 /* 如: 69 5 70 0 4 4 71 0 3 1 72 3 4 2 73 0 2 2 74 0 2 3 75 0 1 2 3 4 76 3 3 3 2 2 77 2到3是区间,区间2,3是1. 78 因此可以左端+1,看成对点更新,就不会连续了。 79 */ 80 } 81 last=-1; 82 query(); 83 for(int i=0;i<=8000;i++) 84 { 85 if(num[i]){ 86 printf("%d %d\n",i,num[i]); 87 } 88 } 89 printf("\n"); 90 } 91 return 0; 92 }