[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");
}

浙公网安备 33010602011771号