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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CF176E Archaeology(set用法提示)

發布時間:2023/12/13 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CF176E Archaeology(set用法提示) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目大意:

給一棵樹,每次激活或熄滅一個點,每次問這些點都聯通起來所需的最小總邊權

分析:

若根據dfs序給所有點排序,為$v1,v2,v3....vk$,那么答案就是$(dis(v1,v2)+dis(v2,v3)+...+dis(vk-1,vk)+dis(vk,v1))/2$

只需要動態的維護這個序列,每次拿出前后兩個點后用lca修改答案即可

這道題主要是想學習一下set在這方面的使用

畢竟現在開O2的題比比皆是,要是能少寫個平衡樹豈不美哉(我也不會寫233

我們就默認使用的是c++11的標準吧


如何為set重載運算符

首先你要有一個結構體,并在里面重載一個bool類型的()函數,先這樣(這里以將數字按d數組的大小排序為例):

struct cmp{bool operator () (const int &a,const int &b){return d[a]<d[b];}};

接下來這樣聲明set:

set<int,cmp>S;

如何查找一個元素的前驅后繼等

我們這里聲明迭代器時使用c++11特有的auto用法,看起來方便不少(set<int>::iterator)

這里以查找x的前驅后繼為例(循環式的,即若x為最后一個數,后繼就是第一個數,反過來同理

auto it=S.lower_bound(x),a=it,b=it; int l=(it==S.begin()?*--S.end():*--a); int r=(it==--S.end()?*S.begin():*++b);

注意這里end()函數返回的是個超尾,所以要--

這里我們看到迭代器的移動用加減即可,取值時用*即可

插入刪除

insert和erase,千萬別記錯了

S.insert(x); S.erase(x);

接下來放上這道題的代碼

1 #include<bits/stdc++.h> 2 #define N 100005 3 #define ll long long 4 using namespace std; 5 int n,q; 6 int h[N],to[2*N],nxt[2*N],w[2*N],etop; 7 void add(int a,int b,int c){to[++etop]=b,nxt[etop]=h[a],w[etop]=c,h[a]=etop;} 8 int fa[N][20],d[N],tot,dep[N]; 9 ll len[N][20]; 10 void dfs(int u){ 11 d[u]=++tot; 12 for(int i=1;i<=17;i++){ 13 fa[u][i]=fa[fa[u][i-1]][i-1]; 14 len[u][i]=len[u][i-1]+len[fa[u][i-1]][i-1]; 15 if(fa[u][i]==0)break; 16 } 17 for(int k=h[u],v=to[k];k;k=nxt[k],v=to[k]) 18 if(v!=fa[u][0]){ 19 fa[v][0]=u;len[v][0]=w[k]; 20 dep[v]=dep[u]+1; 21 dfs(v); 22 } 23 } 24 ll LCA(int x,int y){ 25 ll ans=0; 26 if(dep[x]<dep[y])swap(x,y); 27 for(int i=17;i>=0;i--) 28 if(fa[x][i]&&dep[fa[x][i]]>=dep[y]){ 29 ans+=len[x][i]; 30 x=fa[x][i]; 31 } 32 if(x==y)return ans; 33 for(int i=17;i>=0;i--) 34 if(fa[x][i]!=fa[y][i]){ 35 ans+=len[x][i]; 36 ans+=len[y][i]; 37 x=fa[x][i]; 38 y=fa[y][i]; 39 } 40 ans+=len[x][0]; 41 ans+=len[y][0]; 42 return ans; 43 } 44 struct cmp{bool operator () (const int &a,const int &b){return d[a]<d[b];}}; 45 set<int,cmp>S; 46 ll ans; 47 void ins(int x){ 48 S.insert(x); 49 auto it=S.lower_bound(x),a=it,b=it; 50 int l=(it==S.begin()?*--S.end():*--a); 51 int r=(it==--S.end()?*S.begin():*++b); 52 ans-=LCA(l,r); 53 ans+=LCA(l,x); 54 ans+=LCA(x,r); 55 } 56 void del(int x){ 57 auto it=S.lower_bound(x),a=it,b=it; 58 int l=(it==S.begin()?*--S.end():*--a); 59 int r=(it==--S.end()?*S.begin():*++b); 60 ans+=LCA(l,r); 61 ans-=LCA(l,x); 62 ans-=LCA(x,r); 63 S.erase(x); 64 } 65 char o[2]; 66 int main(){ 67 scanf("%d",&n); 68 for(int i=1,a,b,c;i<n;i++){ 69 scanf("%d%d%d",&a,&b,&c); 70 add(a,b,c),add(b,a,c); 71 } 72 dfs(1); 73 scanf("%d",&q); 74 while(q--){ 75 scanf("%s",o); 76 if(o[0]=='?')cout<<ans/2<<endl; 77 else{ 78 int x;scanf("%d",&x); 79 if(o[0]=='+')ins(x); 80 else del(x); 81 } 82 } 83 return 0; 84 } View Code

?


2019.6.18 update

今天在寫一個掃描線題時使用上面的方法重置set的比較符出現了問題,使用lower_bound會在大數據下WA掉,但upper_bound則沒問題

如果使用常規的重載運算符的話則兩種方式都沒問題……(蒙圈ing

這里給個當時的兩種比較函數吧

這是出了問題的:

struct cmp{bool operator () (const hu &A,const hu &B){double as=A.y+sqrt(A.r*A.r-(A.x-X)*(A.x-X))*(1.0*A.u);double bs=B.y+sqrt(B.r*B.r-(B.x-X)*(B.x-X))*(1.0*B.u);if(as+eps>bs&&bs+eps>as)return A.u<B.u;else return as<bs;} };

這個是改成重載運算符的:

bool operator < (const hu &A,const hu &B){double as=A.y+sqrt(A.r*A.r-(A.x-X)*(A.x-X))*(1.0*A.u);double bs=B.y+sqrt(B.r*B.r-(B.x-X)*(B.x-X))*(1.0*B.u);if(as+eps>bs&&bs+eps>as)return A.u<B.u;else return as<bs; }

如果哪位大神路過希望能指點一下555(;′д`)ゞ

?

還有NOI沒有C++11

所以跟我一起拼一遍

iterator

再來3遍

iterator

iterator

iterator

ojbk!

?

轉載于:https://www.cnblogs.com/2017SSY/p/10948482.html

總結

以上是生活随笔為你收集整理的CF176E Archaeology(set用法提示)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。