daklqw 的 T3(點分樹上資料結構優化DP)

2021-10-08 02:07:28 字數 3971 閱讀 6469

設f

xf_x

fx​為從第x

xx個事件開始做最多的收益。

那麼這個dpdp

dp是按照時間線從後往前的dpdp

dp,求每個點的做起點的答案可以簡單的在每個點初始放乙個a=k

=p=0

a=k=p=0

a=k=p=

0的時間即可解決。

對於兩個事件之間的轉移,我們只需要這兩個事件

在樹上的距離s1s1

s1,最小多走多少距離可以到達乙個獎勵邊刷分並且走回這兩個點的最短路徑s2s2

s2,(貪心來說,如果我們繞路,那麼一定是在乙個最近的獎勵邊上面刷分)

最短路徑上本來有多少獎勵邊ccc。

那麼如果這兩個事件之間可以讓我們移動的事件有ttt,

分類討論一下即可得到在完成這兩個事件的同時我們最多能刷多少分。

預處理出每個點離最近的獎勵邊距離之後,

發現上面三個值都是只和這兩個事件在樹上的路徑有關,可以在點分樹上維護。

那麼一條路徑a→b

a\to b

a→b變成了a→c

→b

a\to c \to b

a→c→b。

要麼中途完全不刷分,在c

cc上面插入時間點:a

aa事件的時間組合上dis

a,

cdis_

disa,c

​,價值:f

af_a

fa​。

b

bb直接在c

cc上面用資料結構查。

要麼a →c

a\to c

a→c中刷分,要麼c→b

c\to b

c→b中刷分。

刷分的話就是對於多餘的2

22秒可以換2c2c

2c的分,對於時間點mod

2\bmod 2

mod2

分別開兩個資料結構維護一下即可。

如果直接上線段樹空間是5

nlog⁡2

n5n\log ^2n

5nlog2

n的,30000

30000

3000

0都過不去。

將所有可能的插入和詢問點,離散化後寫樹狀陣列,乙個詢問只會貢獻o

(log⁡n

)o(\log n)

o(logn

)個點,所以空間複雜度是o(n

log⁡n)

o(n \log n)

o(nlogn)

的。acco

de

\mathcal ac \ code

accode

#include

#define maxn 100005

#define rep(i,j,k) for(int i=(j),lim=(k);i<=lim;i++)

#define per(i,j,k) for(int i=(j),lim=(k);i>=lim;i--)

#define ll long long

#define inf 0x3f3f3f3f3f3f3f3fll

using

namespace std;

char start;

char cb[

1<<16]

,*cs=cb,

*ct=cb;

#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)

template

<

class

t>

void

read

(t &res)

ll c;

int n,q,t;

int h[maxn]

,d[maxn]

,a[maxn]

,k[maxn]

,p[maxn]

,c[maxn]

;int info[maxn]

,prev[maxn<<1]

,to[maxn<<1]

,cst[maxn<<1]

,cnt_e=1;

void

node

(int u,

int v,

int c)

bool

cmp(

const

int&u,

const

int&v)

#define lim 19

int dep[maxn]

,fa[lim]

[maxn]

,fadis[lim]

[maxn]

,faminh[lim]

[maxn]

,facst[lim]

[maxn]

,sz[maxn]

;vector<

int>sb[maxn]

;void

dfs0

(int u,

int ff,

int tsz,

int&mn,

int&rt)if(

(mx =

max(mx , tsz - sz[u]))

< mn)

mn = mx , rt = u;

}int

gert

(int u,

int tsz)

void

ser(

int u,

int ff,

int pa,

int d,

int ndis,

int nh,

int ncst)

void

solve

(int u,

int d)

#define maxp maxn * 250

vectorrt[maxn][5

];intfd

(vector<

int>

&s,int tim)

void

ins(vector

&u,int p,ll v)

ll qry

(vector

&u,int p)

void

upd(

int u,ll val,

int tim,

int dh)

ll qry2

(int u,

int tim,

int dh)

ll qry

(int u,

int tim)

bool

chk(

int a)

char end;

intmain()

rep(i,

1,q)

read

(d[i]),

read

(a[i]),

read

(k[i]),

read

(p[i]

),c[i]

= i;

sort

(c+1

,c+1

+q,cmp)

; queue<

int>q;

rep(i,

1,n)if(

!h[i]

) q.

push

(i);

for(

int u;

!q.empty()

;)solve

(gert(1

,n),0)

;rep

(i,1

,q)}

rep(i,

1,n)

rep(i,

1,q)

rep(i,

1,n)

printf

("%lld%c"

,qry

(i,0),

" \n"

[i==n]);

}

YCH的模擬賽 T3

暴搜或者字典樹,但是因為輸出所有的方案而不是方案數,不管什麼做法都逃不過輸出,所以都差不多 sol1 記憶化搜尋 當列舉方案時,f i 表示已經把字串的前i個字母都拼好的情況下有多少方案 考慮從第i 1個字元開始到j是乙個給定的單詞 如果有這樣的j的話就可以轉移 然後開乙個vector把每乙個狀態下...

T3 顯示隱藏的行業性質

t3顯示隱藏的行業性質 執行sql查詢,輸入以下sql語句 use ufsystem update gl btrade set ctrade name ctrade name where ctrade name in 行政 普通事業 科學事業 建設單位 國家物資儲備 中小學校 高校 社會保險 醫療 ...

JZOJ7月16日提高組T3 樹上路徑

題解現在有一棵n個點的無向樹,每個點的編號在1 n之間,求出每個點所在的最長路。輸入檔名為tree.in。第一行為乙個整數n。之後n 1行,每行三個整數u,v,w,分別表示一條邊連的兩個點和邊權。輸出檔案tree.out,共n行,分別表示經過每個點的最長路。41 2 3 1 3 4 1 4 277 ...