HDU 6521 Party(線段樹 思維)

2021-09-19 08:13:12 字數 2392 閱讀 8410

大致題意:有n個人,一開始相互不認識。他們要去參加party,每次參加的人是編號在區間[l,r]內的人。參加完一次party之後,這區間內的人就會相互認識。現在問你,每次參加party的時候,有多少對人會新認識。

首先,在參加這麼多次party的過程中,每個人認識的人的編號顯然是乙個連續的區間。於是,我們就可以用l[i]和r[i]表示第i個人認識的人的區間左右端點。每次在參加party的過程中,我們實際上是要維護每乙個人的l[i]和r[i]。

但是,直接維護顯然是會超時的。我們考慮尋找一些性質,可以發現對於任意的j>i,一定有l[i]<=l[j]和r[i]<=r[j]。我們可以簡單的證明一下:

如果說l[i]>l[j],那麼說明j認識乙個在i左邊且i不認識的人x。而j要認識x,必然是在某次party中,x和j都參加了。對於這次party來說,x和j參加,那麼必然i也參加,因為參加party是乙個連續區間。所以i和x也相互認識,與條件i和x不認識矛盾。因此我們這條性質成立。

同理對於r[i]根據這個性質,在任意時刻,l[i]和r[i]都是非嚴格單調遞增的。所以對於每次開party的區間[l,r],我們分成前後兩個部分來求。對於前面的部分,我們可以嘗試找到乙個位置pos1使得在pos1之前的人認識的人的右端點小於r,也即在這一次party中,他們要認識後面的人。如此,這一部分要認識的人的對數就是:

同理,對於後面部分,我們同樣也可以找到乙個pos2,使得在pos2之後的人認識的人的左端點大於l,也即在這次party中,他們要認識前面的人。相應的要認識的人的對數就是:

這樣我們就完成了計算。下面看如何維護l和r。在一次party之後,如果在此次之前認識的人的右端點已經大於r或者左端點已經小於l,那麼對於的l和r就不用修改,我們需要修改的只是那些小於r和大於l的點。可以看到,我們還是可以利用剛剛提到的pos,相當於把[l,pos1]的所有r設定為r,把[pos2,r]的所有l設定為l。

總結一下,發現我們需要用乙個可以快速求區間和,能夠查詢大於或者小於某個數的某個位置而且能夠進行區間修改的資料結構。線段樹是不錯的選擇。具體見**:

#include #define inf 0x3f3f3f3f

#define ll long long

#define sc(x) scanf("%d",&x)

#define scc(x,y) scanf("%d%d",&x,&y)

#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)

using namespace std;

const int n = 5e5 + 50;

const int mod = 1e9 + 7;

struct st

t[n<<2];

inline void push_up(int i)

void build(int i,int l,int r)

; if (l==r)

int mid=(l+r)>>1;

build(ls,l,mid);

build(rs,mid+1,r);

push_up(i);

} void push_down(int i)

void update(int i,int l,int r,int x)

if (t[i].lazy!=0) push_down(i);

int mid=(t[i].l+t[i].r)>>1;

if (mid>=r) update(ls,l,r,x);

else if (mid>1;

if (mid>=r) return getsum(ls,l,r);

else if (midx) return t[i].l-1;

else return t[i].l;

}if (t[i].lazy!=0) push_down(i);

if (t[ls].max<=x) query2(i<<1|1,x);

else query2(i<<1,x);

} int query1(int i,int x)

} seg1,seg2;

int main()

pos=seg2.query2(1,r);

if (pos>=l)

printf("%lld\n",ans/2);}}

}

hdu6521 Party(吉司機線段樹)

題意 有n個人,一開始所有人互相不認識。現在有m場party,每場給出l,r,表示編號在 l,r 內的所有人參加,參加之後這些人互相認識。現在要求計算每次party之後會有多少對新的互相認識的人,資料範圍 n,m 2e5 解法 因為區間是連續的,令l i 表示第i個人向左方向認識的最大位置 不需要r...

hdu 預處理 線段樹)

給n個數,m個詢問,問任意區間內與其它數互質的數有多少個 比如3個數1 2 4,詢問 1,3 那麼答案是1 千萬要記住,這樣的題目,如果你不轉變下,使勁往線段樹想 雖然轉變之後,也說要用到線段樹,但是維護的東西不同了 那麼會發現這樣的題目,區間與區間之間是無法傳遞資訊的,區間與區間是無法傳遞資訊的,...

初步線段樹 hdu1166

include include includeusing namespace std define max 50000 struct node node maintree 4 max void settree int n,int l,int r int main printf case d n tt...