洛谷 P2495 [SDOI2011]消耗戰
題目描述
在一場戰爭中,戰場由n個島嶼和n-1個橋梁組成,保證每兩個島嶼間有且僅有一條路徑可達。現在,我軍已經偵查到敵軍的總部在編號為1的島嶼,而且他們已經沒有足夠多的能源維系戰鬥,我軍勝利在望。已知在其他k個島嶼上有豐富能源,為了防止敵軍獲取能源,我軍的任務是炸毀一些橋梁,使得敵軍不能到達任何能源豐富的島嶼。由於不同橋梁的材質和結構不同,所以炸毀不同的橋梁有不同的代價,我軍希望在滿足目標的同時使得總代價最小。
偵查部門還發現,敵軍有一臺神秘機器。即使我軍切斷所有能源之後,他們也可以用那臺機器。機器產生的效果不僅僅會修復所有我軍炸毀的橋梁,而且會重新隨機資源分布(但可以保證的是,資源不會分布到1號島嶼上)。不過偵查部門還發現了這臺機器只能夠使用m次,所以我們只需要把每次任務完成即可。
輸入輸出格式
輸入格式:
第一行一個整數n,代表島嶼數量。
接下來n-1行,每行三個整數u,v,w,代表u號島嶼和v號島嶼由一條代價為c的橋梁直接相連,保證1<=u,v<=n且1<=c<=100000。
第n+1行,一個整數m,代表敵方機器能使用的次數。
接下來m行,每行一個整數ki,代表第i次後,有ki個島嶼資源豐富,接下來k個整數h1,h2,…hk,表示資源豐富島嶼的編號。
輸出格式:
輸出有m行,分別代表每次任務的最小代價。
輸入輸出樣例
輸入樣例#1:10 1 5 13 1 9 6 2 1 19 2 4 8 2 3 91 5 6 8 7 5 4 7 8 31 10 7 9 3 2 10 6 4 5 7 8 3 3 9 4 6
12 32 22
說明
【數據規模和約定】
對於10%的數據,2<=n<=10,1<=m<=5,1<=ki<=n-1
對於20%的數據,2<=n<=100,1<=m<=100,1<=ki<=min(10,n-1)
對於40%的數據,2<=n<=1000,m>=1,sigma(ki)<=500000,1<=ki<=min(15,n-1)
對於100%的數據,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1
這題沒A,先放著,mlog^2n跑這個數據卡不過去
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <cmath> #include <map> #include <stack> #include <set> #include <vector> #include <queue> #include <time.h> #define eps 1e-7 #define INF 0x3f3f3f3f #define MOD 1000000007 #define rep0(j,n) for(int j=0;j<n;++j) #define rep1(j,n) for(int j=1;j<=n;++j) #define pb push_back #define set0(n) memset(n,0,sizeof(n)) #define ll long long #define ull unsigned long long #define iter(i,v) for(edge *i=head[v];i;i=i->nxt) #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define print_runtime printf("Running time:%.3lfs\n",double(clock())/1000.0) #define TO(j) printf(#j": %d\n",j); //#define OJ using namespace std; const int MAXINT = 250010; const int MAXNODE = 100010; const int MAXEDGE = 2 * MAXNODE; char BUF[30000000], *buf; int read() { int x = 0; while (!isdigit(*buf)) buf++; while (isdigit(*buf)) { x = x * 10 + *buf++ - ‘0‘;} return x; } //------------------- Head Files ----------------------// int toid[MAXINT]; struct res { int v, p; res(int _v, int _p) : v(_v), p(_p) {} res() {} }; res add(res a, res b) { return (a.v < b.v ? a : b); } struct node { int lb, rb; node *l, *r; res ans, org; int del, cv, rec; inline void recover() __attribute__((optimize("-O2"))){ del = 0; cv = INF; ans = org; rec = 1; } inline void cover(int c) __attribute__((optimize("-O2"))){ cv = ans.v = c; if (del) del = 0; } inline void dec(int c) __attribute__((optimize("-O2"))){ del += c; ans.v -= c; } inline void pushdown() __attribute__((optimize("-O2"))){ if (rec) { l->recover(); r->recover(); rec = 0; } if (cv != INF) { l->cover(cv); r->cover(cv); cv = INF; } if (del != 0) { l->dec(del); r->dec(del); del = 0; } } inline void pushup() __attribute__((optimize("-O2"))){ ans = add(l->ans, r->ans); } node() { ans.v = del = cv = INF; rec = 0; } }; int n, m, fa[MAXINT], sz[MAXINT], top[MAXINT], dfn[MAXINT], cnt_dfn = 1, dep[MAXINT], cnt, va[MAXINT], val[MAXINT], dfne[MAXINT]; struct SegTree { node mp[MAXINT * 4]; node *root; int _cnt; SegTree() { _cnt = 0; } inline node *newnode(int l, int r) __attribute__((optimize("-O2"))){ node *p = &mp[_cnt++]; p->lb = l; p->rb = r; return p; } inline void maketree(int lb, int rb, node *&p) __attribute__((optimize("-O2"))){ p = newnode(lb, rb); if (rb - lb > 1) { maketree(lb, (lb + rb) / 2, p->l); maketree((lb + rb) / 2, rb, p->r); p->pushup(); } else { p->ans.v = val[p->lb]; p->ans.p = lb; } p->org = p->ans; } inline void del(int lb, int rb, int c) __attribute__((optimize("-O2"))){ del(lb, rb, c, root); } inline void del(int lb, int rb, int c, node *p) __attribute__((optimize("-O2"))){ if (lb >= p->rb || rb <= p->lb) return; if (lb <= p->lb && rb >= p->rb) { p->dec(c); return; } p->pushdown(); del(lb, rb, c, p->l); del(lb, rb, c, p->r); p->pushup(); } inline void cover(int lb, int rb) __attribute__((optimize("-O2"))){ cover(lb, rb, root); } inline void cover(int lb, int rb, node *p) __attribute__((optimize("-O2"))){ if (lb >= p->rb || rb <= p->lb) return; if (lb <= p->lb && rb >= p->rb) { p->cover(0); return; } p->pushdown(); cover(lb, rb, p->l); cover(lb, rb, p->r); p->pushup(); } inline res query(int lb, int rb) __attribute__((optimize("-O2"))){ return query(lb, rb, root); } inline res query(int lb, int rb, node *p) __attribute__((optimize("-O2"))){ if (lb >= p->rb || rb <= p->lb) return res(INF, INF); if (lb <= p->lb && rb >= p->rb) return p->ans; p->pushdown(); return add(query(lb, rb, p->l), query(lb, rb, p->r)); } inline void recover() __attribute__((optimize("-O2"))){ root->recover(); } } st; struct edge { int u, v, l; edge *nxt; edge() {} edge(int _u, int _v, int _l, edge *_nxt) : u(_u), v(_v), l(_l), nxt(_nxt) {} } mp[MAXINT * 2], *head[MAXINT]; inline void addedge(int u, int v, int l) { mp[cnt] = edge(u, v, l, head[u]); head[u] = &mp[cnt++]; mp[cnt] = edge(v, u, l, head[v]); head[v] = &mp[cnt++]; } inline void dfs1(int p) { sz[p] = 1; iter(i, p) { if (i->v == fa[p])continue; fa[i->v] = p; dep[i->v] = dep[p] + 1; va[i->v] = i->l; dfs1(i->v); sz[p] += sz[i->v]; } } inline void dfs2(int p) { int mx = 0, gs = 0; dfn[p] = cnt_dfn++; iter(i, p) { if (i->v == fa[p]) continue; if (sz[i->v] > mx) { mx = sz[i->v]; gs = i->v; } } if (gs == 0) return; top[gs] = top[p]; dfs2(gs); iter(i, p) { if (i->v == fa[p] || i->v == gs) continue; top[i->v] = i->v; dfs2(i->v); } dfne[p] = cnt_dfn; } inline void modify(int l, int r, int c) { while (top[l] != top[r]) { if (dep[top[l]] > dep[top[r]]) { st.del(dfn[top[l]], dfn[l] + 1, c, st.root); l = fa[top[l]]; } else { st.del(dfn[top[r]], dfn[r] + 1, c, st.root); r = fa[top[r]]; } } st.del(min(dfn[r], dfn[l]), max(dfn[r], dfn[l]) + 1, c, st.root); } inline void cover(int p) { st.cover(dfn[p], dfne[p]); } inline res query(int l, int r) { res ans(INF, INF); while (top[l] != top[r]) { if (dep[top[l]] > dep[top[r]]) { ans = add(st.query(dfn[top[l]], dfn[l] + 1), ans); l = fa[top[l]]; } else { ans = add(st.query(dfn[top[r]], dfn[r] + 1), ans); r = fa[top[r]]; } } ans = add(st.query(min(dfn[r], dfn[l]), max(dfn[r], dfn[l]) + 1), ans); return ans; } inline void get_input() __attribute__((optimize("-O2"))); inline void work() __attribute__((optimize("-O2"))); int main() { get_input(); work(); return 0; } inline void work() { dfs1(1); dfs2(1); rep1(i, n) val[dfn[i]] = va[i]; rep1(i, n) toid[dfn[i]] = i; val[1] = INF; st.maketree(1, n + 1, st.root); while (m--) { st.recover(); int k = read(); ll ans = 0; while (k--) { int p = read(); res ret = query(1, p); ans += ret.v; cover(toid[ret.p]); modify(1, fa[toid[ret.p]], ret.v); } printf("%lld\n", ans); } } inline void get_input() { BUF[fread(BUF, 1, 30000000, stdin)] = ‘\0‘; buf = BUF; n = read(); rep0(i, n - 1) { int u = read(), v = read(), l = read(); addedge(u, v, l); } m = read(); } /* 10 1 5 13 1 9 6 2 1 19 2 4 8 2 3 91 5 6 8 7 5 4 7 8 31 10 7 9 1 4 5 7 8 3 */
洛谷 P2495 [SDOI2011]消耗戰