這套題咕咕咕咕咕了好久,還是決定先寫一點吧
從\(i\)到\(j\),在\(j\)處死了,那麼與從\(j\)到\(i\)死的次數是一樣的,也就是說可以向上走到\(lca\)一下的最後一次死的點,最後這一段統計一下需不需要多死一次就好了,樹上倍增記錄\(i\)的第\(2^\)級死亡點,1級死亡點\(dfs\)時候記錄路徑二分查詢即可
code
#include#include#includeusing namespace std;
const int maxn=200005;
struct edgee[maxn<<1|1];
int head[maxn],tot,n,k;
void add(int u,int v,int w)
int fa[maxn][21],dep[maxn],jd[maxn][21],top,rem[maxn];
long long cos[maxn],sum[maxn];
int ef(int x)
return rem[l-1];
}void dfs(int x,int fx)
--top;
}int lca(int x,int y)
int ask(int s,int t)
int main()_\sum^_max(ll[i][0]+rr[j][1],ll[i][1]+rr[j][0],ll[i][0]+rr[j][0])\)
並不好求,轉化一下
\(max(ll[i][0]+rr[j][1],ll[i][1]+rr[j][0],ll[i][0]+rr[j][0])=max(ll[i][1]-ll[i][0],rr[j][1]-rr[j][0],0)+ll[i][0]+rr[j][0]\)
設\(fl[i]=max(ll[i][1]-ll[i][0],0)\)
\(fr[i]=max(rr[i][1]-rr[i][0],0)\)
對答案貢獻轉化為
\(\displaystyle\sum^_\sum^_(ll[i][0]+rr[j][0]+max(fl[i],fr[j]))\)
對\(fl\)
\(fr\)排序,單調指標掃一遍就行了
code#include #include #includeusing namespace std;
const long long maxn=200005;
const long long mod=998244353;
long long n,a[maxn];
const long long inf=0x3f3f3f3f3f3f3f;
long long fl[maxn],fr[maxn],ll[maxn][2],rr[maxn][2];
long long dp[maxn][2],ans;
void work(int l,int r)
int mid=(l+r)>>1;work(l,mid);work(mid+1,r);
//向左,不選mid
dp[mid][0]=0;dp[mid][1]=-inf;
for(int i=mid-1;i>=l;--i)dp[i][0]=max(dp[i+1][0],dp[i+1][1]),dp[i][1]=dp[i+1][0]+a[i],ll[i][0]=max(dp[i][0],dp[i][1]);
//向左,選mid
dp[mid][0]=-inf;dp[mid][1]=a[mid];
for(int i=mid-1;i>=l;--i)dp[i][0]=max(dp[i+1][0],dp[i+1][1]),dp[i][1]=dp[i+1][0]+a[i],ll[i][1]=max(dp[i][0],dp[i][1]);
//向右,不選mid+1
dp[mid+1][0]=0;dp[mid+1][1]=-inf;
for(int i=mid+2;i<=r;++i)dp[i][0]=max(dp[i-1][0],dp[i-1][1]),dp[i][1]=dp[i-1][0]+a[i],rr[i][0]=max(dp[i][0],dp[i][1]);
//向右,選mid+1
dp[mid+1][0]=-inf;dp[mid+1][1]=a[mid+1];
for(int i=mid+2;i<=r;++i)dp[i][0]=max(dp[i-1][0],dp[i-1][1]),dp[i][1]=dp[i-1][0]+a[i],rr[i][1]=max(dp[i][0],dp[i][1]);
ll[mid][0]=0;ll[mid][1]=a[mid];
rr[mid+1][0]=0;rr[mid+1][1]=a[mid+1];
for(int i=l;i<=mid;++i)fl[i]=max(ll[i][1]-ll[i][0],0ll),ans=(ans+ll[i][0]*(r-mid))%mod;
for(int i=mid+1;i<=r;++i)fr[i]=max(rr[i][1]-rr[i][0],0ll),ans=(ans+rr[i][0]*(mid-l+1))%mod;
sort(fl+l,fl+mid+1);sort(fr+mid+1,fr+r+1);
int pl=l,pr=mid+1;
while(pl<=mid)
while(pr<=r)ans=(ans+fr[pr]*(mid-l+1))%mod,++pr;
return;
}int main()
這就是我咕咕咕咕咕了這篇題解這麼長時間的原因
這道題啊,暴力水了90pts,然後正解呢,咕咕咕咕咕咕
NOIP提高組模擬賽3
周圍大佬都說初中打過n遍,我乙個菜雞瑟瑟發抖。把斐波那契數列寫出來找了半天性質,用了半個多小時推出來 x兔子的父親,就是x減去是在斐波那契數列中最大的小於x的數 舉個栗子 13號兔子,應減去8,得到他的祖先5 10號兔子,應減去8,得到他的祖先2 預處理出斐波那契數列,然後讓ab中較大的到他的祖先,...
NOIP提高組模擬賽4
丹青千秋釀,一醉解愁腸 無悔少年枉,只願壯志狂 矩陣字首和加暴力 o n 2m 2 60pts有手就行 觀察資料範圍,猜測應該是求一種 o n 3 的演算法,想到之前做的題,應該是 n 2 枚舉行,n 處理乙個序列的答案,然後,就沒有然後了 對於乙個序列,求子段和為k的倍數,如何 o n 求解,考慮...
NOIP提高組模擬賽6
這題看著真熟啊,好像把之前的english,入陣曲雜糅了一下。首先,像入陣曲一樣計算出字首和 s 式子可以轉化為求 s r s l 1 equiv max mod k 像english一樣 用單調棧處理出以x為最大值的區間,分區間求解 每次列舉一側區間,已知max,只要知道另一側有多少與之餘數相同的...