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$出最短路樹
對於每個節點,符合條件的走法必須滿足,不經過它和它父親之間的連邊
顯然只能從它的某個子節點走向它,就像繞了一圈