1. 程式人生 > >NOIP2018 Day2 T3 保衛王國 - 動態dp - 樹剖 - 線段樹

NOIP2018 Day2 T3 保衛王國 - 動態dp - 樹剖 - 線段樹

直接裸上動態dp即可,因為某些不知道的原因NOIP能過,別的地方不開O2都過不了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define gc getchar()
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef pair<int,int> pii;
inline
int inn() { int x,ch;while((ch=gc)<'0'||ch>'9'); x=ch^'0';while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; } char Type[10]; const int N=100010; struct edges{ int to,pre; }e[N<<1];int p[N],qa[N],qb[N],qx[N],qy[N],h[N],etop; inline int add_edge
(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; } namespace subtask1{ const int N=2010;const lint INF=100000000000ll; int mst[N],mstx[N];lint f[N][2]; int dfs(int x,int fa=0) { f[x][0]=0,f[x][1]=p[x]; for(int i=h[x],y;i;i=e[i].pre) if((y=e[i].to)^fa)
{ dfs(y,x); f[x][0]+=f[y][1]; f[x][1]+=min(f[y][0],f[y][1]); } f[x][0]=min(f[x][0],INF), f[x][1]=min(f[x][1],INF); if(mst[x]) f[x][mstx[x]^1]=INF; return 0; } inline int brute_force_nm(int n,int m) { rep(i,1,m) { int a=qa[i],b=qb[i],x=qx[i],y=qy[i]; mst[a]=mst[b]=1,mstx[a]=x,mstx[b]=y; dfs(1); lint Ans=min(f[1][0],f[1][1]); if(Ans<INF) printf("%lld\n",Ans); else printf("-1\n"); mst[a]=mst[b]=0; } return n-n+0; } } namespace subtask_std{ const lint INF=100000000000; struct node{ int ept;lint w[3][3]; inline node operator+(const node &n)const { node ans;rep(i,0,1) rep(j,0,1) ans.w[i][j]=INF; if(ept) ans=n;if(n.ept) ans=*this;ans.ept=0; if(ept||n.ept) return ans; rep(i,0,1) rep(j,0,1) rep(k,0,1) rep(t,0,1) if(k+t>=1) ans.w[i][j]=min(ans.w[i][j],w[i][k]+n.w[t][j]); return ans; } inline node operator+=(const node &n) { return (*this)=(*this)+n; } inline lint f()const { return min(w[1][0],w[1][1]); } inline lint g()const { return min(w[0][0],w[0][1]); } inline lint ans()const { return min(f(),g()); } }ans; struct segment{ int l,r; segment *ch[2]; node v; }*rt; lint g[N],f[N],fs[N],gs[N];int tms[N],dfc; int in[N],out[N],top[N],bot[N],d[N],fa[N],sz[N],son[N]; inline int push_up(segment* &rt) { return rt->v=rt->ch[0]->v+rt->ch[1]->v,0; } int build(segment* &rt,int l,int r) { rt=new segment,rt->l=l,rt->r=r; if(l==r) { rt->v.w[0][1]=rt->v.w[1][0]=INF, rt->v.w[0][0]=g[tms[l]],rt->v.w[1][1]=f[tms[l]]; return 0; } int mid=(l+r)>>1; build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r); return push_up(rt); } int update(segment* &rt,int p,lint f,lint g) { int l=rt->l,r=rt->r,mid=(l+r)>>1; if(l==r) { rt->v.w[0][1]=rt->v.w[1][0]=INF, rt->v.w[0][0]=g,rt->v.w[1][1]=f; return 0; } update(rt->ch[p>mid],p,f,g);return push_up(rt); } int query(segment* &rt,int s,int t) { int l=rt->l,r=rt->r,mid=(l+r)>>1; if(s<=l&&r<=t) return ans+=rt->v,0; if(s<=mid) query(rt->ch[0],s,t); if(mid<t) query(rt->ch[1],s,t); return 0; } int fir_dfs(int x) { d[x]=d[fa[x]]+1; for(int i=h[x],y;i;i=e[i].pre) if((y=e[i].to)^fa[x]) { fa[y]=x,fir_dfs(y),sz[x]+=sz[y]; if(sz[y]>sz[son[x]]) son[x]=y; } return ++sz[x]; } int sec_dfs(int x) { in[x]=++dfc,tms[dfc]=x; if(son[x]) top[son[x]]=top[x],sec_dfs(son[x]),bot[x]=son[x][bot]; else bot[x]=x; f[x]=p[x],g[x]=0; for(int i=h[x],y;i;i=e[i].pre) if((y=e[i].to)!=fa[x]&&e[i].to!=son[x]) { top[y]=y,sec_dfs(y); f[x]+=min(gs[y],fs[y]); g[x]+=fs[y]; } if(son[x]) fs[x]=f[x]+min(fs[son[x]],gs[son[x]]),gs[x]=g[x]+fs[son[x]]; else fs[x]=f[x],gs[x]=g[x]; out[x]=dfc;return 0; } inline int qry(int x) { ans.ept=1,query(rt,in[x],in[bot[x]]);return 0; } int lst[N]; inline int upd(int x,int v) { int cnt=0; for(int y=top[x],z=fa[y];z;y=top[z],z=fa[y]) lst[++cnt]=y; for(int i=cnt,y,z;i;i--) y=lst[i],z=fa[y],qry(y), update(rt,in[z],f[z]-=ans.ans(),g[z]-=ans.f()); if(v) update(rt,in[x],f[x],g[x]=INF); else update(rt,in[x],f[x]=INF,g[x]); for(int i=1,y,z;i<=cnt;i++) y=lst[i],z=fa[y],qry(y), update(rt,in[z],f[z]+=ans.ans(),g[z]+=ans.f()); return 0; } lint tf[N],tg[N]; inline int back(int x) { update(rt,in[x],f[x]=tf[x],g[x]=tg[x]); for(int y=top[x],z=fa[y];z;y=top[z],z=fa[y]) update(rt,in[z],f[z]=tf[z],g[z]=tg[z]); return 0; } inline int acceptable_solution(int n,int m) { fir_dfs(1),top[1]=1,sec_dfs(1); rep(i,1,n) tf[i]=f[i],tg[i]=g[i]; build(rt,1,n); rep(i,1

相關推薦

NOIP2018 Day2 T3 保衛王國 - 動態dp - - 線段

直接裸上動態dp即可,因為某些不知道的原因NOIP能過,別的地方不開O2都過不了。 #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define lint long long #defi

luogu5024 [NOIp2018]保衛王國 (動態dp)

可以直接套動態dp,但因為它詢問之間相互獨立,所以可以直接倍增記x轉移到fa[x]的矩陣 1 #include<bits/stdc++.h> 2 #define CLR(a,x) memset(a,x,sizeof(a)) 3 using namespace std;

luogu P5024 NOIP2018 保衛王國 動態dp

題意 給你一個樹,每次強制選點或者強制不選,詢問最小權覆蓋 這個東西就是個動態 d p

luoguP5024 保衛王國 動態dp

題目大意: emmmmm 題解: QAQ #include <cstdio> #include <cstring> #include <iostream> using namespace std; #define ll long long #define

bzoj 5210: 最大連通子塊和【動態dp++線段+堆】

參考:https://www.cnblogs.com/CQzhangyu/p/8632904.html 要開longlong的 首先看dp,設f[u]為必選u點的子樹內最大聯通塊,p[u]為不一定選u的子樹內最大聯通塊,轉移很顯然就是f[u]=max(Σf[v],0),p[u]=max(max(p[v]),f

Luogu P4643 【模板】動態dp(矩陣乘法,線段,分)

題面 給定一棵 \(n\) 個點的樹,點帶點權。 有 \(m\) 次操作,每次操作給定 \(x,y\) ,表示修改點 \(x\) 的權值為 \(y\) 。 你需要在每次操作之後求出這棵樹的最大權獨立集的權值大小。 題解 如題所示 , 是個模板題 ... 首先考慮靜態 \(dp\) , 令 \(dp_{u,

旅行[][線段動態開點]

題目描述 S國有N個城市,編號從1到N。城市間用N-1條雙向道路連線,滿足從一個城市出發可以到達其它所有城市。每個城市信仰不同的宗教,如飛天麵條神教、隱形獨角獸教、絕地教都是常見的信仰。 為了方便,我們用不同的正整數代表各種宗教, S國的居民常常旅行。旅行時他們總會走最短路,並且為了避免麻煩

poj3728The merchant+線段

++ swa names include using wap eve scanf mes 如果直接在一條直線上,那麽就建線段樹 考慮每一個區間維護最小值和最大值和答案,就符合了合並的條件,一個log輕松做 那麽在樹上只要套一個樹剖就搞定了,多一個log也不是問題 註意考慮在

POJ3417Network(LCA+樹上查分||+線段

兩個 += gpo scan channels span work received best Yixght is a manager of the company called SzqNetwork(SN). Now she‘s very worried becaus

BZOJ_2157_旅遊_+線段

void span 有時 他還 scanf AI 原來 pushd 每一個 BZOJ_2157_旅遊_樹剖+線段樹 Description Ray 樂忠於旅遊,這次他來到了T 城。T 城是一個水上城市,一共有 N 個景點,有些景點之間會用一座橋連接。為了方便遊客到達

bzoj 4034: [HAOI2015]樹上操作 (+線段操作)

size define next dfs ans n-1 兩個 center mit 4034: [HAOI2015]樹上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6779 Solved: 2275[Sub

LUOGU P1967 貨車運輸(最大生成樹++線段)

main sed != org names dfs 線段 char ons 傳送門 解題思路 貨車所走的路徑一定是最大生成樹上的路徑,所以先跑一個最大生成樹,之後就是求一條路徑上的最小值,用樹剖+線段樹,註意圖可能不連通。將邊權下放到點權上,但x,y路徑上的lca的答案

[BZOJ2325][ZJOI2011]道館之戰(+線段

Address 洛谷P4679 BZOJ2325 Solution 先樹剖,把樹轉成序列。然後線段樹上每個點維護 8 8

LCT++線段+dfs序--bzoj3779: 重組病毒

傳送門 一道資料結構綜合神題(敲的我手都要斷了 首先看三個操作,每次一個新病毒會感染一條鏈,而每個點用的時間就是到根的鏈上不同病毒的數量和,查詢的時候相當於查整個子樹的時間和。 很重要的一個思想是,當一個新病毒感染時,就像

+線段+dfs序+LCA--bzoj3083 遙遠的國度

傳送門 一道樹剖線段樹維護 d f s

LCT++線段--bzoj4817: [Sdoi2017]點塗色

傳送門 和bzoj3379有異曲同工之妙 也是用樹剖+線段樹的思想維護 d f s

+線段--bzoj3626

傳送門 也是一道思路很好的題。 對於一個點 z z z,和一個標號區間

[BZOJ5279][Usaco2018 Open]Disruption(+線段)

題目傳送門 分析   這題我們仔細分析一下,每次斷掉一條樹邊其實就是將一棵樹分成兩部分,然後走一條邊權最短的,端點分別在兩個區域的就行了。那麼轉化一下題意,其實就是對於每一條樹邊,我們要求的就是覆蓋到這條邊的所有給出的m條邊中邊權最小的是多少。轉化完之後實

BZOJ 2402 陶陶的難題II (+線段+凸包+二分)

題目大意:略 一定範圍內求最大值,考慮二分答案 設現在選擇的答案是$mid$,$max \left \{ \frac{yi+qj}{xi+pj} \right \} \geq mid $ 展開可得,$(yi-mid*xi)+(qj-mid*pj)>=0$,只要存在$i,j$使得這個式子成

BZOJ 1576 [USACO]安全路經Travel (+線段)

題目大意: 給你一張無向圖,求1到其他節點 不經過最短路的最後一條邊 的最短路長度,保證每個節點的最短路走法唯一 神題,$USACO$題目的思維是真的好 先$dijkstra$出最短路樹 對於每個節點,符合條件的走法必須滿足,不經過它和它父親之間的連邊 顯然只能從它的某個子節點走向它,就像繞了一圈