bzoj3938 Robot(超哥線段樹)

2021-08-14 16:45:20 字數 3546 閱讀 8310

小q有n只機械人,一開始他把機械人放在了一條數軸上,第i只機械人在ai的位置上靜止,而自己站在原點。在這之後小q會執行一些操作,他想要命令乙個機械人向左或者向右移動x格。但是機械人似乎聽不清小q的命令,事實上它們會以每秒x格的速度勻速移動。看著自己的機械人越走越遠,小q很著急,他想知道當前離他(原點)最遠的機械人有多遠。具體的操作以及詢問見輸入格式。注意,不同的機械人之間互不影響,即不用考慮兩個機械人撞在了一起的情況。

共有m個事件,輸入將會按事件的時間順序給出。第一行兩個正整數n,m。接下來一行n個整數,第i個數是ai,表示第i個機械人初始的位置(初始移動速度為0)。接下來m行,每行行首是乙個非負整數ti,表示該事件點發生的時刻(以秒為單位)。第二個是乙個字串s,代表操作的種類。數字與字串之間用乙個空格隔開。接下來的輸入按s的種類分類。若s=「command」(不帶引號),則接下來兩個整數ki,xi,表示小q對第ki個機械人執行了操作,該機械人的速度將會被重置,變為向數軸正方向每秒移動xi格(若xi為負數就相當於向數軸負方向每秒移動∣xi∣格)。保證1≤ki≤n。若s是「query」(不帶引號),則你需要輸出當前離原點最遠的機械人有多遠。保證t1≤t2≤t2≤…≤tm。(注:若同一時間發生多次操作,則按讀入順序依次執行)

對於每個query詢問,輸出一行,包含乙個整數表示正確的答案。c/c++輸入輸出longlong時請用%lld。由於本題資料量較大,建議不要使用cin/cout進行輸入輸出。

4 5-20 0 20 100

10 command 1 10

20 command 3 -10

30 query

40 command 1 -30

50 query

180280

第乙個命令執行時,各個機械人的位置為:−20,0,20,100。

第二個命令執行時,各個機械人的位置為:80,0,20,100。

第乙個詢問時,各個機械人的位置為:180,0,−80,100。

第三個命令執行時,各個機械人的位置為:280,0,−180,100。

第二個詢問時,各個機械人的位置為:−20,0,−280,100。

限制與約定 設 command 的個數為 c,query 的個數為 q。(所以 c+q=m)

對於所有的事件滿足 0≤ti≤10^9,對於所有的 command 滿足 ∣xi∣≤10^4。

對於所有的機械人滿足 ∣ai∣≤10^9。 n,c<=10^5 q<=5*10^5

每個結點都設定乙個覆蓋標記

如果從來沒有線段覆蓋過,在初次覆蓋的時候直接看一下標記即可

查詢的時候也可以通過判斷標記防止答案錯誤

注意在判斷交點在哪乙個區間的時候,不要忘了線段樹的區間是離散後的時間

if (x<=ti[mid])
啊啊啊啊啊。。。。寫了一下午+一晚上

一開始沒有想明白離散化

後來發現沒有看見是絕對值最大

**量超長180+

if (rreturn;
終於變成了wa

本來是想借鑑一下前輩的**,最後只能找不同了。。。

在處理的時候,我們新增乙個時刻0,方便計算直線的斜率和截距

插入線段時候,我們把每乙個機械人按照操作順序分成若干段分別插入

資料應該是保證時間是單調遞增的

這道題雖然是自己想出來的,但是調了好久。。。

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int inf=1e9;

const

int n=600005;

struct node;

node t[n<<2];

int n,m,nn;

struct point;

point po[n];

ll ti[n],a[n],maxx,minn,nowk[n],nowb[n];

bool f1[n<<2],f2[n<<2];

void change_max(int bh,int l,int r,int l,int r,ll k,ll b)

ll z1=t[bh].mxa*ti[l]+t[bh].mxb; //原線段

ll z2=t[bh].mxa*ti[r]+t[bh].mxb;

ll z3=k*ti[l]+b;

ll z4=k*ti[r]+b;

if (z1>=z3&&z2>=z4) return;

if (z1<=z3&&z2<=z4)

double x=(double)(t[bh].mxb-b)/(k-t[bh].mxa);

if (x<=ti[mid]) //對比的是原時間

}else

}return;

}if (l<=mid) change_max(bh<<1,l,mid,l,r,k,b);

if (r>mid) change_max((bh<<1)+1,mid+1,r,l,r,k,b);

}void change_min(int bh,int l,int r,int l,int r,ll k,ll b)

ll z1=t[bh].mna*ti[l]+t[bh].mnb; //原線段

ll z2=t[bh].mna*ti[r]+t[bh].mnb;

ll z3=k*ti[l]+b;

ll z4=k*ti[r]+b;

if (z1<=z3&&z2<=z4) return;

if (z1>=z3&&z2>=z4)

double x=(double)(t[bh].mnb-b)/(k-t[bh].mna);

if (x<=ti[mid]) //對比的是原時間

}else

}return;

}if (l<=mid) change_min(bh<<1,l,mid,l,r,k,b);

if (r>mid) change_min((bh<<1)+1,mid+1,r,l,r,k,b);

}void ask(int bh,int l,int r,int pos)

int main()

else po[i].type=2;

}int num=m;

ti[++num]=0; //新增乙個初試時刻0

sort(ti+1,ti+1+num); //離散化時間

nn=unique(ti+1,ti+1+num)-ti-1;

for (int i=1;i<=m;i++) if (po[i].type==1)

for (int i=1;i<=n;i++)

for (int i=1;i<=m;i++) if (po[i].type==2)

return

0;}

BZOJ 3938 Robot(超哥線段樹)

題目大意 一條數軸上有n個機械人,對其進行m次操作。操作t i commond k i x i 1 k i n 表示ti時刻將第ki個機械人的速度變為正方向上xi格每秒 操作t i query則是詢問ti時刻離原點最遠的機械人到原點的距離 t1 t2 t3 tm,若同一時間發生多次操作,則按讀入順序...

bzoj3280 小R的煩惱

description 小r最近遇上了 煩,他的程式設計掛科了。於是他只好找程設老師求情。善良的程設老師答應不掛他,但是要求小r幫助他一起解決乙個難題。問題是這樣的,程設老師最近要進行一項 的實驗來證明p np,這個實驗一共持續n天,第i天需要a i 個研究生來給他搬磚。研究生畢竟也是人,所以僱傭研...

bzoj 3280 小R的煩惱

題意 n天,m個學校,k個醫院。每天需要a i 個人,這a i 個人工作後處於瀕死狀態,你可以選擇把瀕死狀態的人送去醫院,治好後還可以繼續工作。每個醫院i救治乙個人需要d i 天,費用q i 元。學校 i 中乙個人工作一天薪酬為p i 思路 時間為乙個天然序,第i天的決策為從健康的人中選擇a i 個...