NOIP 2018 왕국 수호(동적 DP)(LCT)
17005 단어 LCT
#include
#define cs const
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
typedef long long ll;
cs int N = 1e5 + 5;
int first[N], nxt[N << 1], to[N << 1], tot;
void add(int x, int y){
nxt[++tot] = first[x], first[x] = tot, to[tot] = y;
}
int n, m, vl[N];
cs ll INF = 1e15;
void Mi(ll &a, ll b){ if(b < a) a = b; }
struct mat{
ll a[2][2];
mat(){ a[0][0] = a[0][1] = a[1][0] = a[1][1] = INF; }
mat operator * (cs mat &A){
mat B; for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++)
for(int k = 0; k < 2; k++) Mi(B.a[i][j], a[i][k] + A.a[k][j]);
return B;
}
ll mi(){ return min(a[1][0], a[1][1]); }
void init(ll A, ll B){ a[0][1] = a[1][1] = B; a[1][0] = A; }
};
int fa[N], ch[N][2];
mat dp[N], trans[N];
void dfs(int u, int f){
fa[u] = f;
ll A = 0, B = vl[u];
for(int i = first[u]; i; i = nxt[i]){
int t = to[i]; if(t == f) continue;
dfs(t, u);
A += dp[t].a[1][1];
B += dp[t].mi();
}
trans[u].init(A, B);
dp[u].init(A, B);
}
#define ls ch[x][0]
#define rs ch[x][1]
bool isr(int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; }
int get(int x){ return ch[fa[x]][1] == x; }
void pushup(int x){ dp[x] = dp[rs] * trans[x] * dp[ls]; }
void rotate(int x){
int y = fa[x], z = fa[y], k = get(x);
if(!isr(y)) ch[z][get(y)] = x; fa[x] = z;
ch[y][k] = ch[x][k^1]; fa[ch[x][k^1]] = y;
ch[x][k^1] = y; fa[y] = x; pushup(y); pushup(x);
}
void splay(int x){
while(!isr(x)){
int y = fa[x], z = fa[y];
if(!isr(y)) get(x) ^ get(y) ? rotate(x) : rotate(y); rotate(x);
}
}
void access(int x){
for(int y = 0; x; y = x, x = fa[x]){
splay(x);
trans[x].a[0][1] += dp[rs].mi() - dp[y].mi();
trans[x].a[1][1] += dp[rs].mi() - dp[y].mi();
trans[x].a[1][0] += dp[rs].a[1][1] - dp[y].a[1][1];
rs = y; pushup(x);
}
}
void upt(int x, int opt, ll v){
access(x); splay(x);
if(opt == 0){
trans[x].a[0][1] += v;
trans[x].a[1][1] += v;
}
else{
trans[x].a[1][0] += v;
} pushup(x);
}
int main(){
n = read(), m = read();
dp[0].a[0][0] = 0;
dp[0].a[1][1] = 0;
char opt[5]; scanf("%s", opt);
for(int i = 1; i <= n; i++) vl[i] = read();
for(int i = 1; i < n; i++){
int x = read(), y = read();
add(x, y); add(y, x);
} dfs(1, 0);
while(m--){
int a = read(), x = read(), b = read(), y = read();
upt(a, x, INF);
upt(b, y, INF);
splay(1);
if(dp[1].mi() >= INF) puts("-1");
else cout << dp[1].mi() << '
';
upt(a, x, -INF);
upt(b, y, -INF);
} return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[BZOJ2049][SDOI2008]Cave동굴탐사LCT누드문제모형문제수조판수조, 적어도 현재 나는 수조만 쓰고 지침은 쓰지 않는다. LCT 같은 건 말 안 할 거야. 엉망진창이야. 어차피 이 편은 자용이야. 마찬가지로 이 블로그를 보는 사람들은 먼저 다른 곳에 가서 LCT를 배운 후에 나...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.