題意: 簡化就是有兩種操作,一種是插入(x,y,z)這個座標,第二種是查詢(x1,y1,z1)到(x2,y2,z2)(x1<=x2,y1<=y2,z1<=z2)的長方體包含多少個點。
解析: 將查詢分成8個點,離線做,離散化z值,
兩次cdq,第一次歸併排x值,第二次歸併排y值,z值用bit樹維護更新
查詢。**
#include#includeview code#include
#include
using
namespace
std;
const
int maxn=9*50000
;int
n,q,ans[maxn];
struct
node
}a[maxn],b[maxn],c[maxn];
//a儲存原陣列,b儲存中間過程,c用於歸併排序臨時陣列
bool cmpid(const node& a,const node& b)
void add(int i,int d)
int sum(int
i)void cdq2(int l,int r) //
歸併排y值,對z值查詢更新
if(b[rs].s!=0) ans[b[rs].id]+=sum(b[rs].z)*b[rs].s; //
右邊的是查詢
rs++;
}while(ls>l) //
恢復 ls=l,rs=mid+1
;
for(int i=l;i<=r;i++) //
歸併排序過程,排y值
for(int i=l;i<=r;i++) b[i]=c[i];
}void cdq1(int l,int r)//
歸併排x值,選取的過程是時序
if(k>0) cdq2(0,k-1); //
再一次cdq
ls=l,rs=mid+1
;
for(int i=l;i<=r;i++) //
歸併排序
for(int i=l;i<=r;i++) a[i]=c[i];
}int
main()
else
}memset(ans,
0,sizeof
(ans));
sort(a,a+n,cmpz); //
按照z值排序
int ka=1
; a[n].z=-1
;
for(int i=0;i)
if(a[i].z!=a[i+1].z) a[i].z=ka++; //
離散化else a[i].z=ka;
sort(a,a+n,cmpid); //
按照時序排回來
memset(tree,0,sizeof
(tree));
cdq1(
0,n-1
); sort(a,a+n,cmpid); //
再排回來
for(int i=0;i//
輸出答案
}return0;
}
HDU 3400 兩次三分
這道題卡了我好久,一直不能證明他們的距離為什麼是先遞減後遞增,所以也不能想到三分 網上也沒有給出證明,嘗試用三分寫了下,注意是三分的e,f點在ab cd點上的佔的比例,這樣 比較簡單好看 include include include define eps 1e 8 struct point poi...
HDU 2612 Find a way(兩次廣搜)
分析這道題直接兩次bfs,累加兩個人分別到達同一kfc的最短時間,然後遍歷找到到達所有kfc時間之和最小的位置。注意如果時間為0,說明沒有到達過。include include include includeusing namespace std define inf 0x3f3f3f3f cons...
hdu 1254 推箱子(兩次廣搜)
這題乙個下午了,現在終於過了 用了兩次廣搜,一次搜箱子到目標地,第二次搜人是可以到推動箱子的地方,要注意的是箱子可能會阻擋人,也可以來回的推。給幾組資料就知道了 這題資料都是後面討論版中提供的 4 30 0 0 0 0 1 0 2 3 1 4 1 5 50 3 0 0 0 1 0 1 4 0 0 0...