linker
總分 : 100 + 100 + 40 = 240
結論題。無論如何神j都會贏。
最優決策:神樹變化了我就不變,神樹不變我就變化。
#includeusing namespace std;
typedef long long ll;
const int mod=998244353;
inline ll pow(ll pre, int x)
int n;
int main()
狀壓dp水題。
暴力都沒有去切,因為k太小了,直接狀壓走過那些邊即可。
//**有點醜,但是考試的時候挺快就敲出來了。
#include#define re register
#define rep(i,a,b) for(re int i=a,i##end=b; i<=i##end; i++)
#define drep(i,a,b) for(re int i=a,i##end=b; i>=i##end; i--)
#define repp(i,a,b) for(re int i=a,i##end=b; ii##end; i--)
#define erep(i,x) for(re int i=head[x]; i; i=edge[i].nxt)
#define lowbit(x) ((x)&-(x))
#define debug(x) cerr<<#x<<" = "<#define pll pair#define fi first
#define se second
#define coint const int
#define coll const ll
#define cm cerr<<(&s2-&s1)/1024./1024<<"mb"templateinline t max(const t &x, const t &y)
templateinline t min(const t &x, const t &y)
struct edge2;
vectorg[n];
vectorvec;
int n,m,k;
int mark[n],id[n];
ll dis[k<<1][n];
ll dp[(1<_.val; }
};struct heap
} }// rep(i,1,n) printf("%d -> %d : %lld\n",st,i,dis[id][i]);
return;
}bool s2;
int main()
} mark[1]=1;
rep(i,1,n) if(mark[i]) vec.push_back((int)i),id[i]=((int)vec.size())-1;
ms(mark,-1); ms(dis,0x3f);
repp(i,0,vec.size()) dijkstra(i,vec[i]);
ms(dp,0x3f);
coll inf=dp[0][0];
dp[0][0]=0;
repp(sta,0,(1<=inf) continue;
int at=vec[i];
repp(j,0,(int)g[at].size())
} }ll ans=inf;
repp(i,0,vec.size())
ans=min(ans,dp[(1<(pre_dfs與dfs_top是樹鏈剖分的部分。)
p30直接暴力\(o(n^3)\)處理處每兩個點間最小dis值
struct p30
rep(i,1,n)
x=f[x];
}} rep(i,1,m)
printf("%lld\n",dis[s][t]);
} return;
}}p30;
p40
可以發現詢問數量很小,我們直接對於每個詢問暴力向上跳,而我們總共就會處理\(n^2\)個點之間的距離,中間重複處理的還可以省去,因此總複雜度不到\(o(n^2)\)
struct p40
rep(i,1,m)
int x=t,fa=f[s];
if(!mark[s][t]) while(x!=fa)
int y=t;
while(y!=x)
mark[x][t]=1;
x=f[x];
}printf("%lld\n",dis[s][t]);
} return;
}}p40;
p70
可以發現在向下跳的過程中,我們經過的點是單調遞減的,因此利用倍增思想,記錄下乙個走到的點,以及其花費,然後倍增處理處即可。
struct p_chain
if(tp[0][x]) dis[0][x]=x*(dis[tp[0][x]]-dis[x]);
} return;
} inline void solve()
} rep(i,1,m)
ll ans=0;
drep(j,19,0)
stk[++tail]=x;
}} return; }
struct elementb[n];
inline int get_element(int x, int y)
b[++cnt]=(element)<%x,y%>;
return cnt; }
inline void solve()
} while(m--)
if(l[t]r[s])
int cnt=get_element(s,t);
ll ans=0;
int mn=s;
drep(i,cnt,1)
if(to[0][l] && l[to[0][l]]<=l[r]) ans+=mn*(dis[to[0][l]]-dis[l]),l=to[0][l],mn=l;
drep(j,19,0)
if(i>1) ans+=mn*(dis[b[i-1].l]-dis[l]);
else ans+=mn*(dis[r]-dis[l]);
}printf("%lld\n",ans);
} return;
} }p100;
鏈的30分沒拿到真的不應該。思維還得更加活躍才可以。 牛客CSP S提高組賽前集訓營2
然後隨便用乙個資料結構維護一下就行了,我寫的線段樹。我們先找出每個環,然後我們先刪連線環的邊,每刪一條就可以多產生乙個聯通塊,在考慮刪環邊,發現從最大的環刪起一定最優 因為你刪的第一條邊得不到任何新的聯通塊 就很容易想到tar jantarjan tarjan 發現你只能寫出80 8080 分,因為...
牛客CSP S提高組賽前集訓營1
比賽鏈結 官方題解 before t1觀察 結論題,t2樹形dp,可以換根或up down,t3正解妙,轉化為圖上問題。題目質量不錯,但資料太水了 一共n個石子堆,每個石子堆有ai個石子,兩人輪流對石子塗色 先手塗紅,後手塗藍 且需要保證當前回合塗的石子顏色不能和它相鄰的兩個同色,誰塗不下去誰輸。一...
牛客CSP S提高組賽前集訓營5(待更)
題目描述 神樹大人造了乙個長為n的01序列,並邀請無所事事的神j來和他博弈。每一輪裡,若這個序列的第1項是0,那麼神樹大人可以選擇讓它不變或者變成1 若這個序列的第1項是1,那麼神j可以選擇讓它不變或者變成0。接著對這個序列進行旋轉操作 即將第1項放到第n項的後面,其他項依次替補。如果這個序列變為全...