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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)

發(fā)布時(shí)間:2024/4/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

\(STL\)坑害了一個晚上,真的菜的沒救了啊。

準(zhǔn)確的說是一個叫\(reverse\ iterator\)的東西,就是我們經(jīng)常用的\(rbegin()\)

有一個非常重要的性質(zhì)

在反向迭代器中,++相當(dāng)于正常的--,--相當(dāng)于正常的++

也就是說
假設(shè)我們要訪問\(set\)中的倒數(shù)第二個元素,我們要\(++s.rbegin()\)

而不是一些別的東西


我們回到這個題,對于這個題目來說,其實(shí)我的第一反應(yīng)是虛樹,QWQ但事實(shí)證明,并不能用虛樹來解決這個問題。

我們可以通過一些方式,發(fā)現(xiàn),無論從哪個有寶藏的點(diǎn)出發(fā),訪問所有點(diǎn)的總距離都是一定的。那么我們可以強(qiáng)制按照\(dfn\)順序,每個點(diǎn)從\(dfn\)的上一個節(jié)點(diǎn)走過來,然后走向\(dfn\)的下一個節(jié)點(diǎn),那么刪除的之后,我們要是知道每個點(diǎn)的前驅(qū)和后繼的話,就可以考慮直接更新\(ans\)了,(但是要特判第一個點(diǎn)和最后一個點(diǎn),第一個點(diǎn)的前驅(qū)是最后一個點(diǎn),最后一個點(diǎn)的后繼是第一個點(diǎn))

那么既然需要一個排序+前驅(qū)后繼的數(shù)據(jù)結(jié)構(gòu),自然就是\(set\)

不過需要注意的是。

\(rbegin()\)的問題!!!!!!!!!!!!!!

直接給代碼了

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> #include<set> #define mk makr_pair #define ll long long #define int long long using namespace std; inline int read() {int x=0,f=1;char ch=getchar();while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f; } const int maxn = 2e5+1e2; const int maxm = 2*maxn; const int inf = 1e9; int point[maxn],nxt[maxm],to[maxm]; int cnt,n,m; int dfn[maxn],deep[maxn],f[maxn][21]; set<int> s; int tot; int dis[maxn]; int mp[maxn]; int ans; int val[maxm],tag[maxn]; void addedge(int x,int y,int w) {nxt[++cnt]=point[x];to[cnt]=y;val[cnt]=w;point[x]=cnt; } void dfs(int x,int fa,int dep) {deep[x]=dep;dfn[x]=++tot;mp[tot]=x;for (int i=point[x];i;i=nxt[i]){int p = to[i];if (p==fa) continue;f[p][0]=x;dis[p]=dis[x]+val[i];dfs(p,x,dep+1);} } void init() {for (int j=1;j<=20;j++)for (int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1]; } int go_up(int x,int d) {for (int i=0;i<=20;i++)if ((1<<i) & d) x=f[x][i];return x; } int lca(int x,int y) {if (deep[x]>deep[y]) x=go_up(x,deep[x]-deep[y]);else y=go_up(y,deep[y]-deep[x]);if (x==y) return x;for (int i=20;i>=0;i--){if (f[x][i]!=f[y][i]){x=f[x][i];y=f[y][i];}}return f[x][0]; } int getdis(int x,int y) {return dis[x]-2*dis[lca(x,y)]+dis[y]; } int getpre(int x) {set<int> :: iterator it = s.lower_bound(x);--it;if ((*it)==-inf) return mp[*(++s.rbegin())];else return mp[(*it)]; } int getlas(int x) {set<int> :: iterator it = s.upper_bound(x);if ((*it)==inf) return mp[*(++s.begin())];else return mp[(*it)]; } signed main() {//freopen("game.in.txt","r",stdin);//freopen("game.out","w",stdout);n=read();m=read();for (int i=1;i<n;i++){int x=read(),y=read(),w=read();addedge(x,y,w);addedge(y,x,w);}dfs(1,0,1);init();s.insert(inf);s.insert(-inf);for (int i=1;i<=m;i++){int x=read();if (tag[x]){int pre = getpre(dfn[x]);int last = getlas(dfn[x]);// cout<<"you:"<<pre<<" "<<last<<endl;ans=ans-getdis(pre,x)-getdis(last,x);ans=ans+getdis(pre,last);s.erase(dfn[x]);tag[x]=0;}else{if (s.size()==2) {s.insert(dfn[x]);tag[x]=1;cout<<ans<<"\n";continue;}int pre = getpre(dfn[x]); //cout<<1<<endl; int last = getlas(dfn[x]);// cout<<"meiyou:"<<pre<<" "<<last<<" "<<getdis(pre,x)<<" "<<lca(pre,x)<<" "<<dis[pre]<<" "<<dis[x]<<endl;ans=ans-getdis(pre,last);ans=ans+getdis(pre,x)+getdis(last,x);s.insert(dfn[x]);tag[x]=1;}cout<<ans<<"\n";}return 0; }

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

總結(jié)

以上是生活随笔為你收集整理的洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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