[zoj]3573 Under Attack I
这道题是一区间统计,注意炸弹炸的是线段,最后要求的是最大的损坏值D_max,最左的具有D_max的线段的左起点,和,最右的具有D_max的线段的右起点。
因为是离线统计(废话,炸着炸药你就去修路啊~~),所以未必要用线段树
全长 [0, len] 在数轴上。离散也就是 0, 1, … , len-1 ( n = [n, n+1] )
10
1 5 2
6 9 2
也就是[5, 6]无损
把[a, b] +d拆成 [a, infinity] +d, [b,infinity] -d
即可。
O, 上面理解错了,还是理解成点【0,len】也就是len+1个点,对【a,b】操作就是对(b-a+1)个点操作
2781797 2012-02-26 17:12:29 Accepted 3573 C++ 2140 540 wyfyw #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <cmath> #include <algorithm> using namespace std; const int M=15005; typedef long long LL; LL A[M],B[M],R[M]; int main() { //freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); int len; while(cin>>len) { memset(A,0,sizeof(A)); memset(B,0,sizeof(B)); int s,e,d;//start end damage while(scanf("%d %d %d",&s,&e,&d)) { if(s==-1)break; if(s>e) swap(s,e); A[s]+=d; B[e+1]-=d; } int ansL=0,ansR=0; LL max=-1; LL now=0; for(int i=0; i<=len; i++) { now+=A[i]+B[i]; R[i]=now;//restoring for the R->L traversal if(max<now) { ansL=i; max=now; } } for(int i=len; i>=0; i--) { if(R[i]==max) { ansR=i; break; } } printf("%d %d\n",ansL,ansR); } //fclose(stdout); return 0; }
线段树写法
2781808 2012-02-26 17:19:14 Accepted 3573 C++ 3900 656 wyfyw /* 线段树写法: 两个性质: 1、如果整段+ad,则这段的max+=ad 2、每段的max=max(lmax,rmax)+ad //记得每次清空 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<map> #include<algorithm> using namespace std; struct node { int mx,ad; } tree[15005*4]; void build(int st,int ed,int p) { tree[p].ad=0; tree[p].mx=0; if(st==ed) { return; } int m=(st+ed)/2; build(st,m,p*2); build(m+1,ed,p*2+1); } void insert(int st,int ed,int ll,int rr,int ad,int p) { if(st==ll && ed==rr) { tree[p].ad+=ad; tree[p].mx+=ad; return;// tree[p].mx; } int m=(st+ed)/2; if(rr<=m) { insert(st,m,ll,rr,ad,p*2); } else if(ll>=m+1) { insert(m+1,ed,ll,rr,ad,p*2+1); } else { insert(st,m,ll,m,ad,p*2); insert(m+1,ed,m+1,rr,ad,p*2+1); } tree[p].mx=max(tree[p*2].mx, tree[p*2+1].mx)+tree[p].ad; } int findst(int st,int ed,int p) { //printf("ad & mx= %d %d\n",tree[p].ad,tree[p].mx); if(st==ed) return st; int m=(st+ed)/2; if(tree[p*2].mx>=tree[p*2+1].mx) return findst(st,m,p*2); else return findst(m+1,ed,p*2+1); } int finded(int st,int ed,int p) { if(st==ed) return st; int m=(st+ed)/2; if(tree[p*2].mx>tree[p*2+1].mx) return finded(st,m,p*2); else return finded(m+1,ed,p*2+1); } int main() { int n; while(scanf("%d",&n) != EOF ) { n++; build(1,n,1/*at node 1*/);//del//?[0,1]=>1...[n-1,n]=>n int a,b,c,i=0; while(scanf("%d%d%d",&a,&b,&c)) { if(a>b) swap(a,b); if(a==-1) break; a++, b ++;//del//?[st,end]=>st+1...end insert(1,n,a,b,c,1); } int st,ed; st=findst(1,n,1); ed=finded(1,n,1); printf("%d %d\n",st-1,ed -1);//del//? } //system("pause"); }