日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

李超线段树 [Heoi2013]Segment

發(fā)布時間:2023/12/10 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 李超线段树 [Heoi2013]Segment 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

問題 D: [Heoi2013]Segment
時間限制: 4 Sec 內(nèi)存限制: 256 MB
題目描述
要求在平面直角坐標(biāo)系下維護(hù)兩個操作:
1.在平面上加入一條線段。記第i條被插入的線段的標(biāo)號為i。
2.給定一個數(shù)k,詢問與直線 x = k相交的線段中,交點最靠上的線段的編號。

輸入

第一行一個整數(shù)n,表示共n 個操作。
接下來n行,每行第一個數(shù)為0或1。

若該數(shù)為 0,則后面跟著一個正整數(shù) k,表示詢問與直線
x = ((k +lastans–1)%39989+1)相交的線段中交點(包括在端點相交的情形)最靠上的線段的編號,其中%表示取余。若某條線段為直線的一部分,則視作直線與線段交于該線段y坐標(biāo)最大處。若有多條線段符合要求,輸出編號最小的線段的編號。
若該數(shù)為 1,則后面跟著四個正整數(shù) x0, y0, x 1, y 1,表示插入一條兩個端點為
((x0+lastans-1)%39989+1,(y0+lastans-1)%10^9+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的線段。
其中l(wèi)astans為上一次詢問的答案。初始時lastans=0。

輸出
對于每個 0操作,輸出一行,包含一個正整數(shù),表示交點最靠上的線段的編號。若不存在與直線相交的線段,答案為0。

樣例輸入
6
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5
樣例輸出
2
0 3
提示
對于100%的數(shù)據(jù),1 ≤ n ≤ 10^5 , 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。

其實這道題就是個板子,李超線段樹。(這個板子就是為了解決這個問題,只不過板子太難了而已,汗顏)

就題論算法把,李超線段樹用來處理向一個區(qū)間加有斜率的線段,之后判斷某位置權(quán)值最大的線段是哪條之類的問題。而最重要的是多了的insert函數(shù)。當(dāng)分到的區(qū)間已屬于這條線段覆蓋的區(qū)間是,就要進(jìn)行更神奇的操作了,去比較當(dāng)前節(jié)點所存的最優(yōu)線段。先附上代碼。

void insert(int l,int r,int x,int k) {if(!t[x].h)t[x].h=k;if(cmp(t[x].h,k,l))swap(t[x].h,k);if(l==r||a[t[x].h].k==a[k].k)return;int mid=(l+r)/2;double g=(double)(a[t[x].h].b-a[k].b)/(a[k].k-a[t[x].h].k);if(g<l||g>r)return;if(g<=mid)insert(l,mid,x*2,t[x].h),t[x].h=k;else insert(mid+1,r,x*2+1,k); }

因為比較分為兩種情況,完全壓制和在區(qū)間內(nèi)有交點。完全壓制不動或直接修改后返回就好了。而對于相交的就必須求出交點,根據(jù)交點的位置(其實也就是判斷那條線段在交點那一邊處于優(yōu)勢)去修改子區(qū)間。
對于這段代碼理解還是有點困難(本蒟蒻太水,自己口胡。。)要把本區(qū)間右側(cè)較大的線段置成本區(qū)間最優(yōu)(我也不是太懂為什么。。望神犇來解釋),若不懂,手動模擬一下過程即可。
還要注意一些細(xì)節(jié):直線斜率是否存在,以及兩條線是否平行。。(RE到死)

#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 101000 #define ll long long using namespace std; struct node {int l,r,id;double k,b; }a[N]; struct tree{int l,r,h;}t[50000*4]; int n,m; void build(int l,int r,int x) {t[x].l=l;t[x].r=r;if(l==r){t[x].h=0;return;}int mid=(l+r)/2;build(l,mid,x*2);build(mid+1,r,x*2+1); } bool cmp(int x,int y,double l) {if(!x)return 1;double l1=a[x].k*l+a[x].b,l2=a[y].k*l+a[y].b;return l1!=l2?l1<l2:x<y; } int q(int k,int x) {if(t[x].l==t[x].r)return t[x].h;int mid=(t[x].l+t[x].r)/2,tmp;if(k<=mid)tmp=q(k,x*2);else tmp=q(k,x*2+1);return cmp(t[x].h,tmp,k)?tmp:t[x].h; } void insert(int l,int r,int x,int k) {if(!t[x].h)t[x].h=k;if(cmp(t[x].h,k,l))swap(t[x].h,k);if(l==r||a[t[x].h].k==a[k].k)return;int mid=(l+r)/2;double g=(double)(a[t[x].h].b-a[k].b)/(a[k].k-a[t[x].h].k);if(g<l||g>r)return;if(g<=mid)insert(l,mid,x*2,t[x].h),t[x].h=k;else insert(mid+1,r,x*2+1,k); } void c(int k,int x) {if(t[x].l>=a[k].l&&t[x].r<=a[k].r){insert(t[x].l,t[x].r,x,k);return;}int mid=(t[x].l+t[x].r)/2;if(a[k].l<=mid)c(k,x*2);if(a[k].r>mid)c(k,x*2+1); } int main() {scanf("%d",&n);int x1,x2,y1,y2,z,ans=0;build(1,50000,1);while(n--){scanf("%d",&z);if(z==0){scanf("%d",&x1);x1=(x1+ans-1)%39989+1;//out<<x1<<endl;ans=q(x1,1);printf("%d\n",ans);}else{m++;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);x1=(x1+ans-1)%39989+1;x2=(x2+ans-1)%39989+1;y1=(y1+ans-1)%1000000000+1;y2=(y2+ans-1)%1000000000+1;//cout<<x1<<" "<<x2<<" "<<y1<<" "<<y2<<endl;if(x1>x2)swap(x1,x2),swap(y1,y2);if(x1==x2)a[m].k=0,a[m].b=max(y1,y2);else{a[m].k=(double)(y1-y2)/(x1-x2);a[m].b=(double)y1-a[m].k*x1;}a[m].l=x1;a[m].r=x2;a[m].id=m;c(m,1);}} }

轉(zhuǎn)載于:https://www.cnblogs.com/QTY2001/p/7632656.html

總結(jié)

以上是生活随笔為你收集整理的李超线段树 [Heoi2013]Segment的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。