首先字首和的變化一定是連續的。那麼對於每個區間,我們找到他最大值和最小值所在的位置,如果k在最小最大值之間,那麼一定可以從最小值最大值位置所構成的區間中得到。
那麼根據單調性二分就可以了。每次二分出乙個位置用杜教篩計算一下。
對於最大值最小值所在的位置可以打表啊。
這道題以前做過乙個靜態的,就是樹在開始的時候直接建好,後面直接查詢。
這道題的關鍵是需要看出集合的構建實際上是一顆樹結構,每次就是找到所以點的lca然後新加入的點就是lca的乙個新的兒子。
對於查詢,我們需要對於所有點按照dfs序排序,然後容斥計算答案。乙個點的貢獻va
l 就是他到根路徑上所有ci
的和。所以我們需要用平衡樹動態的維護dfs序和每個點的va
l
#include
#include
#include
#include
#include
#define n 1200003
using namespace std;
int ch[n][3],fa[n],delta[n],val[n],a[n],ci[n],b[n],n;
int l[n],r[n],cnt,root,f[n][21],mi[21],deep[n],size[n];
int tot,point[n],nxt[n],v[n],sz;
struct dataq[n];
void pushdown(int x)
int get(int x)
void update(int x)
void rotate(int x)
void splay(int x,int tar)
int pre()
int next()
void build(int x,int y)
}void
add(int
f1,int
v,int
x)int
lca(int
x,int
y)int cmp(data a,data b)
intmain()
if (k==1)
intt=lca(a[1],a[2]);
for (int
j=3;j<=k;j++)
t=lca(t,a[j]);
add(t,x,sz);
build(t,sz);
}if (s[1]=='u')
if (s[1]=='q')
sort(q+1,q+k+1,cmp);
ans=0;
splay(l[q[1].a],0);
ans+=val[root];
for (int
j=2;j<=k;j++)
printf("%d\n",ans);}}
}
省隊集訓Round2 DAY3
用splay維護權值有序。每次加入乙個人,貪心的選出前i 1個人中要求最小的vi 1,判斷能否滿足,如果能滿足就把這vi 1個人的權值 1,剩下的人不需要他們的支援,那麼都賦值成0,並且把這些點移動到平衡樹中0所在的位置 如果不能滿足就直接在平衡樹中加入乙個 1.要求每乙個時間每條邊只能有乙個人經過...
省隊集訓Round2 DAY7
考慮最暴力的做法,實際上就是列舉選中區間的左右端點,然後用點分判斷選出的點構成的合法路徑和未選中的點構成的合法路徑的大小。如果再優化一點可以,列舉其中乙個端點,另乙個端點動態的維護,有點類似動態點分的樣子。這麼做的瓶頸在於列舉端點。首先如果右端點如果右移的話,那麼滿足條件的區間左端點的位置實際上是單...
省隊集訓DAY2
假設我們列舉數列中長度為len的區間,那麼如何判斷兩個數列可以匹配呢?對於提取的數列從小到大排序,從大到小排序,然後兩兩配對,如果所有的都滿足 h 那麼就可以匹配。應該算是貪心吧。這樣做的時間複雜度是o n le n loglen 還是上面的思想,我們如何快速判斷呢?假設我們確定了提取出的區間數列,...