主要說一下特殊的建圖方式,自己腦補了一下,發現和題解不一樣
首先,建出反串 sam,然後把每個 \(a_i\) 掛到對應的 sam 節點上,按照長度從小到大排序
然後把每個 sam 節點拆成 2 個 \(s, t\),\(s\) 向當前節點上掛的第乙個 \(a_i\) 連邊,邊權是 \(|a_i|\)(長度),\(a_i\) 向後面的節點連邊,邊權是 \(|a_| - |a_|\)(長度差),最後乙個節點 \(a_k\) 向 \(t\) 連邊權是 \(-|a_k|\) 的邊,然後 \(t\) 向原來的這個節點的兒子連邊權是 0 的邊
如果 \(a_i\) 能控制 \(b_j\) 直接從 \(a_i\) 向 \(b_j\) 連邊,權值為 0
找出每個 \(b_i\) 對應的節點,二分一下,找到長度 \(\ge |b_i|\) 的第乙個點 \(a_i\),向它連邊權為 \(|a_i|\) 的邊
最後拓撲排序找最長路就行了
#include using namespace std;
#define gc getchar
#define rg register
#define i inline
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define per(i, a, b) for(int i = a; i >= b; --i)
i int read()
const int n = 4e5 + 5, m = n << 2;
int tr[n][26], len[n], lst, link[n], cnt, star[n >> 1], dfn[n], bk[n];
int fa[n][19], n, na, nb, pos[n];
int head[m], ver[m << 1], nxt[m << 1], tot, edge[m << 1], deg[m];
long long f[m];
int base;
vectorg[n << 1];
void add(int x, int y, int z)
char s[n];
struct node
node(){}
node(int l, int r, int id): l(l), r(r), id(id) {}
};vectorh[n];
i void prepro()
cnt = lst = 1;
}i void insert(int c, int id) }}
void dfs(int x)
i void build()
i int getfa(int l, int r)
return x;
}i long long topu()
} if(num != base) return -1;
return f[1];
}i void main()
base = cnt;
rep(i, 1, cnt)else add(i, bk[i], 0);
} nb = read();
rep(i, 1, nb));
if(it == h[pos[i]].end()) add(base + na + cnt + i, bk[pos[i]], 0);
else add(base + na + cnt + i, base + it -> id, it -> r - it -> l + 1);
} base += na + nb + cnt;
int m = read();
rep(i, 1, m)
printf("%lld\n", topu());
}signed main()
十二省聯考2019 遊記
在機房呆了一天,大概看了看原先寫過的題,有點頹。下午的時候和大家一起打掃了一下機房。走的時候,看著空無一字的黑板,風吹起的棕黃色窗簾,遠方的藍色天空,有一種很濃厚的哀傷。時間過得真快啊,轉眼就是省選了呢。許是要退役了吧?許是要退役了吧。下午去試機了,感覺鍵盤不太星啊。考場倒是換了乙個地方 但是不讓我...
P5290 十二省聯考2019 春節十二響
傳送門 考慮乙個子樹裡是怎麼劃分的,維護劃分出來的每個集合的最大值,這個可以用乙個 multiset 維護 設 s x 表示節點 x 的子樹中,最優劃分 劃分出來的每個塊的節點最大值 首先葉子節點的集合顯然只有它本身 然後考慮子樹之間的合併,設兩個子樹根節點為 x,y 因為兩個子樹之間一定不會有祖先...
P5290 十二省聯考2019 春節十二響
考試的時候,本來想拿60的貪心,但是只拿了15 很不開心!不過現在知道正解了qwq 對於每個點,都開乙個優先佇列,這個優先佇列裡的值,代表這個點的子樹分成的若干個集合中最大的值。那麼我們對於乙個沒有處理的點,分別列舉每乙個子樹,分別合併每乙個優先佇列,最後再加入這個點,得到新的優先佇列。對於正確性,...