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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

NOIP2016洛谷P1600:天天爱跑步

發(fā)布時間:2023/12/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NOIP2016洛谷P1600:天天爱跑步 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 解析
    • sol1:樹剖+map
    • sol2:樹剖+離線
    • sol3:dfs維護(hù)樹狀數(shù)組+差分

解析

個人認(rèn)為本題比同年的逛公園可做許多

本題的一個關(guān)鍵是:把慢跑者(u,v)(u,v)(u,v)轉(zhuǎn)化為上升路徑上滿足depx+tx=depudep_x+t_x=dep_udepx?+tx?=depu?的結(jié)點和下降路徑上滿足?dep+x+tx=depu?2?deplca-dep+x+t_x=dep_u-2*dep_{lca}?dep+x+tx?=depu??2?deplca?的結(jié)點x的答案均加一

這個感覺不是很難想,由于每秒跑一步的特性,很容易想到這個和深度的聯(lián)系

然后就是怎么維護(hù)上面那個玩意了

sol1:樹剖+map

時間復(fù)雜度:O(nlogn^3)
得分:95pts
這是我一開始想到的解法
第一交95pts也可以接受了吧
極其好寫
就是對線段樹每個結(jié)點開個map,做一個標(biāo)記永久化,然后詢問的時候沿途把標(biāo)記撿起來就行了
修改過程中只會在最終打標(biāo)記處改變map
一開始我覺得這個改變次數(shù)是O(1)的,但是這個是**假的!!**在最差情況下會退化成Ologn個(比如修改[1,n-1]的區(qū)間時)
這樣復(fù)雜度就升到了nlogn^3,無法通過了
T掉3e5的數(shù)據(jù)也是合情合理
由于樹剖自帶的小常數(shù)+氧氣加持+上面那個第三個log完全跑不滿(現(xiàn)在終于可以默認(rèn)有O2了!),得到95分也算合理
(然而關(guān)掉氧氣由于垃圾的map常數(shù)就只有25pts)

sol2:樹剖+離線

時間復(fù)雜度:nlogn^2
得分:100pts
稍微思考一下就可以想到真的做法
注意到所有的操作和詢問都是針對一個特定的值,把他們離線下來從大到小處理即可
詢問的時候用到一個先減后加從而求出變化量
這個就跑的飛快了
也不再耗氧
### 代碼

#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline #define debug(a,b) fprintf(stderr,a,b) const int N=3e5+100; const double eps=1e-9; inline ll read() {ll x=0,f=1;char c=getchar();while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m; struct node {int to,nxt; } p[N<<1]; int fi[N],cnt; inline void addline(int x,int y) {p[++cnt]=(node) {y,fi[x]};fi[x]=cnt;return; } int fa[N],siz[N],dep[N],hson[N],top[N],dfn[N],pos[N],tim; void dfs1(int x,int f) {fa[x]=f;dep[x]=dep[f]+1;siz[x]=1;for(int i=fi[x]; ~i; i=p[i].nxt) {int to=p[i].to;if(to==f) continue;dfs1(to,x);siz[x]+=siz[to];if(siz[to]>siz[hson[x]]) hson[x]=to;}return; } void dfs2(int x,int tp) {top[x]=tp;dfn[++tim]=x;pos[x]=tim;if(hson[x]) dfs2(hson[x],tp);for(int i=fi[x]; ~i; i=p[i].nxt) {int to=p[i].to;if(to==hson[x]||to==fa[x]) continue;dfs2(to,to);}return; } inline int Lca(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x=fa[top[x]];} if(dep[x]<dep[y]) swap(x,y);return y; }#define mid ((l+r)>>1) #define ls (k<<1) #define rs (k<<1|1)int ans[N];struct tree{int val[N<<2];int ask(int k,int l,int r,int x){int res=val[k];if(l==r) return res;if(x<=mid) return ask(ls,l,mid,x)+res;else return ask(rs,mid+1,r,x)+res;}void change(int k,int l,int r,int x,int y){if(x>y) return;//printf("k=%d (%d %d) x=%d y=%d v=%d\n",k,l,r,x,y,v);if(x<=l&&r<=y){val[k]++;return;}if(x<=mid) change(ls,l,mid,x,y);if(y>mid) change(rs,mid+1,r,x,y);return;}inline void Add(int x,int anc,int flag){while(top[x]!=top[anc]){change(1,1,n,pos[top[x]],pos[x]);x=fa[top[x]];}change(1,1,n,pos[anc]+flag,pos[x]);return;} }t[2];int tt[N];int tot1,tot2; struct ope{int x,anc,val,op;bool operator < (const ope u)const{return val<u.val;} }o[N<<1]; struct query{int x,val,op;bool operator < (const query u)const{return val<u.val;} }q[N<<1]; int main() { #ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout); #endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1; i<n; i++) {int x=read(),y=read();addline(x,y);addline(y,x);}dfs1(1,0);dfs2(1,1);for(int i=1;i<=n;i++){tt[i]=read();q[++tot1]=(query){i,tt[i]+dep[i],0};q[++tot1]=(query){i,tt[i]-dep[i],1};}//for(int i=1;i<=n;i++) printf("x=%d fa=%d dep=%d t=%d pos=%d v1=%d v2=%d\n",i,fa[i],dep[i],t[i],pos[i],t[i]+dep[i],t[i]-dep[i]);for(int i=1;i<=m;i++){int x=read(),y=read();int lca=Lca(x,y);o[++tot2]=(ope){x,lca,dep[x],0};o[++tot2]=(ope){y,lca,dep[x]-2*dep[lca],1};//t1.Add(x,lca,dep[x],1);//t2.Add(y,lca,dep[x]-2*dep[lca],0);//printf("x=%d y=%d lca=%d v1=%d v2=%d\n",x,y,lca,dep[x],dep[x]-2*dep[lca]);}sort(q+1,q+1+tot1);sort(o+1,o+1+tot2);int pl1=1,pl2=1;for(int tim=-2*n;tim<=2*n;tim++){for(int i=pl1;i<=tot1&&q[i].val==tim;i++){int now=q[i].x;ans[now]-=t[q[i].op].ask(1,1,n,pos[now]);}while(pl2<=tot2&&o[pl2].val==tim){t[o[pl2].op].Add(o[pl2].x,o[pl2].anc,o[pl2].op);++pl2;}while(pl1<=tot1&&q[pl1].val==tim){int now=q[pl1].x;ans[now]+=t[q[pl1].op].ask(1,1,n,pos[now]);++pl1;}}for(int i=1;i<=n;i++){printf("%d ",ans[i]);}return 0; } /* 6 1 2 3 1 2 1 4 4 5 4 6 0 2 5 1 2 3 1 5 */

sol3:dfs維護(hù)樹狀數(shù)組+差分

時間復(fù)雜度:nlogn
得分:100pts
寫完看的題解的思路
這個東西是真的好強(qiáng)大
有點四兩撥千斤的感覺
以后可以多往這方面想一想
就是把我上面維護(hù)的東西離線到各個結(jié)點上
維護(hù)樹狀數(shù)組并利用前后差值求出答案
(應(yīng)該)跑的飛快
說是應(yīng)該是因為我并沒有再寫一遍

總結(jié)

以上是生活随笔為你收集整理的NOIP2016洛谷P1600:天天爱跑步的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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