兩個區間:[si, ei] 和 [sj, ej] (0 <= s < e <= 10^5)若 si <= sj,且 ej <= ei 且 ei - si > ej - sj, 則第i個區間覆蓋第j個區間,即牛i比牛j強壯。問對於每一頭牛i有多少頭牛比它強壯。
這題先一看,不知如何下手。首先,將每個區間的s和e當做是(s,e)乙個點,這樣子把所有點在座標系上畫出來,你就會發現乙個很神奇的現象,題目要求就會變成:問每乙個點的左上角有多少個點?那麼這題轉化為了,每個點的左上角有多少個點。但是點不是有序排好的,要預處理一下就可以。
如果正常做,那個y是遞增的,所以sum和update那個方向就會相反了,這個其實沒什麼所謂,一樣的,排序的時候先y由大到小排,y相同時x由小到大排,這樣小小的處理,就變成stars那題了!
首先將e[i]降序排序如果相等,則按s[i]的公升序排序。那麼執行完這部操作之後前面的
e[i]肯定 >= 後面的e[i],現在只要考慮s[i]就好了,每次計算s[i]之前有多少個點。
統計完之後將s[i]的位置加1,並更新線段樹。
這題需要離散化,如果兩頭牛的區間相同,則當前牛比它大的個數等於前面牛比它大的個數。ac**
#include
#include
#include
#define ls o*2
#define rs o*2+1
using
namespace
std;
const
int n = 1e5 + 10;
struct cow cow[n];
int sumv[n << 2], ans[n];
bool cmp(cow a, cow b)
int ql, qr;
int query(int o, int l, int r)
int p, v;
void modify(int o, int l, int r)
int m = (l + r)/2;
if(p <= m) modify(ls, l, m);
else modify(rs, m+1, r);
sumv[o] = sumv[ls] + sumv[rs];
}int main()
sort(cow+1, cow+1+n, cmp);
memset(sumv, 0, sizeof(sumv));
for(int i = 1; i <= n; i++) else
p = cow[i].s, v = 1;
modify(1, 1, n);
}printf("%d", ans[1]);
for(int i = 2; i <= n; i++) puts("");
}return
0;}
POJ 2481 Cows 線段樹 樹狀陣列
給出n個區間 輸出每個區間 是多少個區間的真子集 思路 區間左端點為第一關鍵字,右端點第二關鍵字,前者公升序後者降序 這樣對每個區間i,只需要查詢 ri到n有多少個右端點就是答案,可能有好幾個區間相同,那麼預處理一下最後減掉完全相同的區間即可 include include include incl...
poj 2481 Cows 樹狀陣列or線段樹
題意 給n個區間,問第i個區間是多少個區間的子區間。分析 可以吧每乙個線段看成是乙個點,這樣的話就等價於問乙個點的左上方有多少個點?這樣就和stars那題一樣了。因為是求左上方有多少個點,那麼把所有點按照y從大到小排列,這樣就可以按照順序求出0 x之間有多少個點,就是它左上方的點了。需要重點的處理。...
poj 2481 Cows 樹狀陣列or線段樹
題意 給n個區間,問第i個區間是多少個區間的子區間。分析 可以吧每乙個線段看成是乙個點,這樣的話就等價於問乙個點的左上方有多少個點?這樣就和stars那題一樣了。因為是求左上方有多少個點,那麼把所有點按照y從大到小排列,這樣就可以按照順序求出0 x之間有多少個點,就是它左上方的點了。需要重點的處理。...