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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU - 6183 暴力,线段树动态开点,cdq分治

發(fā)布時間:2025/3/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 6183 暴力,线段树动态开点,cdq分治 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

B - Color itHDU - 6183?

  題目大意:有三種操作,0是清空所有點,1是給點(x,y)涂上顏色c,2是查詢滿足1<=a<=x,y1<=b<=y2的(a,b)點一共有幾種不同的顏色

  一開始做的時候直接就是開51個vector保存每個顏色相應(yīng)的點,然后就是詢問就是,暴力循環(huán)判斷這個顏色存不存在一個滿足條件的點,感覺最差情況下應(yīng)該會超時,不過卻過了

1 #include<cstdio> 2 #include<vector> 3 using namespace std; 4 struct Node{ 5 int x,y; 6 Node(){} 7 Node(int x,int y):x(x),y(y){} 8 }; 9 vector<Node> c[58]; 10 int main() 11 { 12 int op,x,y,y1,cc; 13 while(scanf("%d",&op)&&op!=3) 14 { 15 if(op==0) 16 { 17 for(int i=0;i<=50;i++) 18 c[i].clear(); 19 } 20 else if(op==1) 21 { 22 scanf("%d%d%d",&x,&y,&cc); 23 c[cc].push_back(Node(x,y)); 24 } 25 else 26 { 27 scanf("%d%d%d",&x,&y,&y1); 28 int ans=0; 29 for(int i=0;i<=50;i++) 30 { 31 for(int j=0;j<c[i].size();j++) 32 if(c[i][j].x<=x&&c[i][j].y>=y&&c[i][j].y<=y1) 33 { 34 ans++; 35 break; 36 } 37 } 38 printf("%d\n",ans); 39 } 40 } 41 return 0; 42 } 暴力過一切

  然后看網(wǎng)上有是線段樹動態(tài)開點的做法,但實際上并不比上面暴力的寫法快,反而慢上幾十ms,不過可以當做一個算法擴展來聯(lián)系。

  首先1操作肯定就是單點更新了,而2操作上已經(jīng)限定了x的左邊為1,所以我們以y軸來建線段樹維護個區(qū)間內(nèi)x的最小值,那么2操作就是區(qū)間查詢了。但我們知道正常靜態(tài)的線段樹需要4*SIZE的節(jié)點空間來保存信息的,在這里又需要51顆線段樹,也就是51*4*1000000的空間來保存節(jié)點信息,不知道你們電腦能不能開那么大的數(shù)組,反正我的電腦和OJ的虛擬機是不行的。但其實最多150000個1操作和2操作,并不需要那么大的空間。所以這時候需要用到線段樹的動態(tài)開點了。

  靜態(tài)的線段樹,每個編號為x的節(jié)點,它的左孩子編號就為2*x,右孩子編號就為2*x+1,然后這個節(jié)點x,我們是保存它的區(qū)間L,R和其他一系列信息。而動態(tài)開點的話,對于編號為x的節(jié)點,它的左右孩子的編號就不一定是2*x和2*x+1的關(guān)系了,所以我們要保存下的是它的左右孩子的編號已經(jīng)一系列相關(guān)的信息,然后對于每個節(jié)點就是當需要到它時再開辟它。其他操作就和靜態(tài)的線段樹差不多。

1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N=1001108; 5 struct Tree{ 6 int lson,rson,minx; 7 }T[N]; 8 int tn,flag,root[52]; 9 //root就保存這個顏色對于的那棵線段樹的根節(jié)點編號 10 void init() 11 { 12 tn=1; 13 for(int i=0;i<=50;i++) 14 root[i]=0; 15 } 16 void updata(int &id,int L,int R,int y,int x)//在這里用L,R來表示節(jié)點id的區(qū)間 17 { 18 if(!id) 19 {//需要到這個節(jié)點了,開辟這個節(jié)點 20 id=tn++; 21 T[id].minx=N; 22 T[id].lson=T[id].rson=0;//它的子節(jié)點還未用得上 23 } 24 T[id].minx=min(T[id].minx,x);//更新最小的x值 25 //下面就是線段樹的單點修改 26 if(L==R) 27 return ; 28 int mid=(L+R)>>1; 29 if(y<=mid) 30 updata(T[id].lson,L,mid,y,x); 31 else 32 updata(T[id].rson,mid+1,R,y,x); 33 } 34 void query(int id,int L,int R,int l,int r,int x) 35 { 36 if(flag||!id)//如果已經(jīng)有點滿足條件,或者這個節(jié)點沒開辟就返回 37 return ; 38 if(l<=L&&r>=R) 39 { 40 if(T[id].minx<=x) 41 flag=1;//在y1和y2范圍內(nèi)有個x滿足條件 42 return ; 43 } 44 int mid=(L+R)>>1; 45 if(l<=mid) 46 query(T[id].lson,L,mid,l,r,x); 47 if(r>mid) 48 query(T[id].rson,mid+1,R,l,r,x); 49 } 50 int main() 51 { 52 int op,x,y,y2,c; 53 init(); 54 while(~scanf("%d",&op)&&op!=3) 55 { 56 if(op==0) 57 init(); 58 else if(op==1) 59 { 60 scanf("%d%d%d",&x,&y,&c); 61 updata(root[c],1,1000000,y,x); 62 } 63 else 64 { 65 scanf("%d%d%d",&x,&y,&y2); 66 int ans=0; 67 for(int i=0;i<=50;i++) 68 { 69 flag=0; 70 query(root[i],1,1000000,y,y2,x); 71 ans+=flag; 72 } 73 printf("%d\n",ans); 74 } 75 } 76 return 0; 77 } 線段樹下線段果

  正解是cdq分治,待我學(xué)成歸來,再更新。。。我回來了

  cdq分治處理的話,就是三維偏序的一個處理,(操作時間,x軸,y軸),然后第一維已經(jīng)有序,那么我們cdq分治處理第二維,然后線段樹處理第三維。因為最多是50種顏色,那么我們采用狀壓的策略,把每個顏色C用2C來表示,然后線段樹維護個區(qū)間或和。需要注意的就是y軸離散化下,不然容易超時。

1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #define L(x) (x<<1) 5 #define R(x) (x<<1|1) 6 #define M(x) ((T[x].l+T[x].r)>>1) 7 using namespace std; 8 typedef long long ll; 9 const int N=150118,Y=1000118; 10 struct Tree{ 11 int l,r; 12 ll val; 13 }T[Y]; 14 struct Nop{ 15 int op,x,y,y1; 16 ll val;//op1更新操作的val記錄2^C,op2查詢操作記錄答案編號 17 friend bool operator <(const Nop &n1,const Nop &n2){ 18 return n1.x==n2.x ? n1.op<n2.op : n1.x<n2.x; 19 } 20 }P[N<<1],temp[N<<1]; 21 int pn=0,qn=0,newy[Y]; 22 bool num[Y]={0}; 23 vector<int> vy; 24 ll ans[N]={0},cf2[52]={1}; 25 inline void addp(int op,int x,int y,int y1,ll val){ 26 P[pn++]=(Nop){op,x,y,y1,val}; 27 } 28 inline void addy(int y) 29 { 30 if(!num[y]) 31 { 32 num[y]=1; 33 vy.push_back(y); 34 } 35 } 36 void built(int id,int l,int r) 37 { 38 T[id].val=0; 39 T[id].l=l,T[id].r=r; 40 if(l==r) 41 return ; 42 built(L(id),l,M(id)); 43 built(R(id),M(id)+1,r); 44 } 45 //線段樹單點修改 46 void updata(int id,int pos,ll val) 47 { 48 if(T[id].l==T[id].r&&T[id].l==pos) 49 { 50 if(val) 51 T[id].val|=val; 52 else 53 T[id].val=0; 54 return ; 55 } 56 if(pos<=M(id)) 57 updata(L(id),pos,val); 58 else 59 updata(R(id),pos,val); 60 T[id].val=T[L(id)].val|T[R(id)].val; 61 } 62 //區(qū)間或和查詢 63 ll query(int id,int l,int r) 64 { 65 ll ans=0; 66 if(l<=T[id].l&&T[id].r<=r) 67 return T[id].val; 68 if(l<=M(id)) 69 ans|=query(L(id),l,r); 70 if(r>M(id)) 71 ans|=query(R(id),l,r); 72 return ans; 73 } 74 void cdq(int l,int r) 75 { 76 if(l==r) 77 return ; 78 int m=(l+r)>>1; 79 cdq(l,m); 80 cdq(m+1,r); 81 int i=l,j=m+1,k=l; 82 while(i<=m&&j<=r) 83 { 84 if(P[i]<P[j]) 85 { 86 if(P[i].op==1) 87 updata(1,P[i].y,P[i].val); 88 temp[k++]=P[i++]; 89 } 90 else 91 { 92 if(P[j].op==2) 93 ans[P[j].val]|=query(1,P[j].y,P[j].y1); 94 temp[k++]=P[j++]; 95 } 96 } 97 while(i<=m) 98 temp[k++]=P[i++]; 99 while(j<=r) 100 { 101 if(P[j].op==2) 102 ans[P[j].val]|=query(1,P[j].y,P[j].y1); 103 temp[k++]=P[j++]; 104 } 105 for(i=l;i<=r;i++) 106 { 107 if(P[i].op==1) 108 updata(1,P[i].y,0); 109 P[i]=temp[i]; 110 } 111 } 112 void solve() 113 { 114 if(pn) 115 { 116 //離散化部分 117 sort(vy.begin(),vy.end()); 118 for(int i=0;i<vy.size();i++) 119 { 120 newy[vy[i]]=i+1; 121 num[vy[i]]=0; 122 } 123 for(int i=0;i<pn;i++) 124 { 125 if(P[i].op==1) 126 P[i].y=newy[P[i].y]; 127 else 128 P[i].y=newy[P[i].y],P[i].y1=newy[P[i].y1]; 129 } 130 //進行分治 131 cdq(0,pn-1); 132 } 133 for(int i=0;i<qn;i++) 134 { 135 int sum=0; 136 //判斷2^0+2^1+2^2+...+2^50含有哪些 137 for(int j=0;j<=50;j++) 138 if(ans[i]&cf2[j]) 139 sum++; 140 printf("%d\n",sum); 141 ans[i]=0; 142 } 143 pn=qn=0; 144 vy.clear(); 145 } 146 int main() 147 { 148 int op,x,y,c,y1; 149 built(1,1,N); 150 for(int i=1;i<=50;i++) 151 cf2[i]=cf2[i-1]<<1; 152 while(~scanf("%d",&op)&&op!=3) 153 { 154 if(op==0) 155 solve(); 156 else if(op==1) 157 { 158 scanf("%d%d%d",&x,&y,&c); 159 addp(1,x,y,0,cf2[c]); 160 addy(y); 161 } 162 else 163 { 164 scanf("%d%d%d",&x,&y,&y1); 165 addp(2,x,y,y1,qn++); 166 addy(y); 167 addy(y1); 168 } 169 } 170 solve(); 171 return 0; 172 } 一分二二分四

  但實際上,3個實現(xiàn)方法中,暴力最快。。。數(shù)據(jù)太坑了

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

總結(jié)

以上是生活随笔為你收集整理的HDU - 6183 暴力,线段树动态开点,cdq分治的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 欧美激情一区二区 | 欧美日韩高清一区二区 国产亚洲免费看 | 色综合久久五月 | 成人午夜网 | 在线看视频 | 日本啪啪动态图 | 潮喷失禁大喷水aⅴ无码 | 国产三级漂亮女教师 | 日本狠狠爱| 桃色一区 | 就去吻亚洲| 久久久亚洲天堂 | 蜜臀尤物一区二区三区直播 | 欧美成人激情视频 | 国产三级第一页 | 宅男在线视频 | 伊人伦理 | 久久国产精品国语对白 | 日韩色图一区 | 精品在线免费播放 | 国产亚洲色婷婷久久99精品91 | 国产精品jizz在线观看无码 | 欧美一区二区福利视频 | 久久久久久久久蜜桃 | 玩弄丰满少妇xxxxx性多毛 | 老司机深夜福利在线观看 | 男女啪啪无遮挡 | 理论黄色片 | 亚av | japan高清日本乱xxxxx | 中文字幕无码av波多野吉衣 | 国产在线123 | 国产区高清 | 成人午夜在线免费观看 | 免费av在线播放网址 | 国产午夜视频 | 777精品 | 色吧婷婷| 久久久久99精品成人片我成大片 | 一本色道久久综合亚洲精品酒店 | 亚洲中文字幕无码不卡电影 | 911精品国产一区二区在线 | 亚洲精品尤物 | 成人网页| 亚洲国产成人在线观看 | 亚洲黄片一区二区 | 91久久国产视频 | 一级视频在线观看 | 亚欧洲乱码视频 | 国产小视频免费在线观看 | 一区二区视频在线播放 | 涩涩视频网 | 热久久伊人 | 色综合网站 | 91久久精品国产91久久性色tv | 一区二区三区免费看 | 日本特黄网站 | 日本在线高清视频 | 国产人妻一区二区三区四区五区六 | 日韩中文在线视频 | 黄色不雅视频 | 日韩三级免费 | 日本女人毛片 | 露出调教羞耻91九色 | 韩日一级片 | 波多野结衣电影在线播放 | 国产中文一区二区三区 | 日韩精品在线观看网站 | 亚洲综合视频在线播放 | 久久精品导航 | 美女视频免费在线观看 | 国产黄色小说 | 黄色片在线免费 | 精品欧美日韩 | 波多野结衣视频在线播放 | 中文字幕丝袜诱惑 | 亚洲天堂性| 亚洲黄页网站 | h片在线免费 | 全部孕妇毛片丰满孕妇孕交 | 天天插天天狠 | 亚洲一区影院 | 婷婷久久久久久 | 日韩色在线 | 91久久精品国产91性色69 | 日本免费三片在线播放 | 日日干日日干 | 高h av | 国产二级一片内射视频播放 | 色播开心网 | 欧美性猛交xxxx黑人交 | mm1313亚洲国产精品无码试看 | www.69视频| 成人综合网址 | 亚洲爱爱网站 | 超碰一区 | 午夜久久久久久久久 | 国产欧美视频在线播放 | av视|