給出\(n\)個點\((x_i,y_i)\),\(m\)次給出\((k_i,a_i)\)表示標記所有滿足
\[y_j>\frac}
\]的未標記點
求每個點的標記時間
\(1\leq n,m\leq 10^5,1
全是乘法所以可以先左右取\(ln\)就是
\[ln(y_j)>ln(k_i)-ln(x_j)\times a_i
\]把\(x,y,k\)取\(ln\)然後就是乙個順眼的式子
\[x_j\times a_i+y_i>k_i
\]雖然原題說\((x_i,y_i)\)是點,但是我們可以換個思路,把\((x_i,y_i)\)看成邊(\(f(z)=x_iz+y_i\)),\((a_i,k_i)\)看成是點,然後問在每條邊下面的編號最小的點是哪個。
這個就很好解決了,考慮整體二分。每次要考慮對於一條邊是否有在\([l,mid]\)編號的點在它下面。可以對於所有的\([l,mid]\)的點拿出來構成乙個下凸殼,然後根據每條邊的斜率二分出乙個最下面的點,然後只拿這個點判斷就好了。
這樣就是\(o(n\log^2 n)\)的了,如果肯寫歸併排序和凸殼用單調佇列維護是可以做到\(o(n\log n)\)的
#include#include#include#includeusing namespace std;
const int n=1e5+10;
int n,m,f[n],s[n],p[n],p1[n],p2[n],top,pos[n];
double x[n],y[n],k[n],z[n];
double xj(double x1,double y1,double x2,double y2)
double xl(int a,int b,int c)
bool cmp(int x,int y)
int mid=(lm+rm)>>1;top=0;
sort(pos+lm,pos+1+mid,cmp);
for(int i=lm;i<=mid;i++)
sort(pos+lm,pos+1+mid);
int cnt1=0,cnt2=0;
for(int i=ln;i<=rn;i++)
if(x[p[i]]*z[s[l]]+y[p[i]]>k[s[l]])p1[++cnt1]=p[i];
else p2[++cnt2]=p[i];
} for(int i=1;i<=cnt1;i++)p[i+ln-1]=p1[i];
for(int i=1;i<=cnt2;i++)p[ln+cnt1+i-1]=p2[i];
solve(ln,ln+cnt1-1,lm,mid);
solve(ln+cnt1,rn,mid+1,rm);
return;
}int main()
for(int i=1;i<=m;i++)
solve(1,n,1,m);
for(int i=1;i<=n;i++)
if(f[i]==m)puts("-1");
else printf("%d\n",f[i]);
return 0;
}
雷達裝置 Ybtoj
有n nn個建築物,第i ii個建築物在笛卡爾座標系上的座標為 xi yi x i,y i xi y i 你需要在x xx軸上安裝一些雷達,每個雷達的偵察半徑均為d dd,要求每個建築物都至少被乙個雷達偵測到,求最少要安裝幾個雷達。第一行兩個正整數n,d n,dn,d。接下來n nn行,第i ii行...
YBTOJ 電路維修
思路 乍一看這題,沒有bfs的頭緒 但是,我們想到了spfa 我們可以把地圖中的每個點看成方格,這樣就有 n 1 m 1 個方格 如果兩點之間有線聯通,那它們之間的邊權就是0,否則就為1 然後spfa就可以了 include include include using namespace std i...
YBTOJ 守衛挑戰
有 n 項任務,有乙個數 k 每一項任務成功的概率是 p i 這裡與原題目不同,原題目是百分之 p i 這裡相當於 p i frac 成功後會使 k 加上 a i 問至少成功 l 次且最後 k leq0 的概率是多少。資料範圍 0 leq k leq2000,0 leq l leq n leq 20...