\(f_i\) 表示以 \(i\) 為結尾的答案,然後轉移為 \(f_i=\max\limits_^(f_j+(a_i-a_j)^2+c)\)
這樣會有不合法的情況無法轉移,就是兩個數之間有比他倆都大的值
但是這樣的值一定會比從最大值轉移要劣,所以直接斜率做一下就行
code
#include#define int long long
#define lson rt<<1
#define rson rt<<1|1
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}int n,c,ans;
int a[1000010],f[1000010];
inline int sq(int x)
struct node
}st[1000010*4];
inline bool cover(node a,node b,int x)
void build(int rt,int l,int r)
void ins(int rt,int l,int r,node k)
int query(int rt,int l,int r,int pos)
signed main());
for(int i=2;i<=n;i++));
} printf("%lld\n",f[n]);
return 0;
}
先詢問出全域性的最大差值,然後二分乙個位置找到任意乙個極值的位置
因為每個數都不一樣,於是與極值作差的結果也都不一樣
再按二進位制位拆分,每個差值都會在是二進位制下是 \(1\) 的那一位出現一次
於是就能找出每個位置與極值的差,然後再找出最大的那個位置
詢問一下,看看一開始的值是最大值還是最小值然後就能知道出所有數的值了
code#include "difference.h"
#includeusing namespace std;
namespace ttt
for(int i=0;(1<>i&1;
vec.clear();
for(int j=1;j<=n;j++) if((j>>i)&1) if(j-1!=pos) vec.emplace_back(j-1);
s=qry2(vec);for(auto l:s) mp[i][l]--;
vec.clear();
for(int j=1;j<=n;j++) if((j>>i)&1) if(j-1!=pos) vec.emplace_back(j-1);
vec.emplace_back(pos);
s=qry2(vec);for(auto l:s) mp[i][l]++;
} for(int i=0,sum;i>j)&1)else for(auto l:mp[j]) if(l.second!=0) t[l.first]+=1000;
for(auto l:t) if(l.second==sum) c[i]=l.first;
} for(int i=0,tmx=-1;i
咕咕咕
省選模擬12 題解
暴力做法是直接bfs。優化的方法是離散化。將特殊的點的橫縱座標抽出來,然後用這些橫縱座標為1e12 1e12分成乙個個塊,容易發現每個塊內的狀態是一致的。然後用與暴力類似的方法即可,注意最後統計的是每個塊的實際大小。觀察可知資料範圍欺騙了你。似乎剪枝 注意去重複狀態 的搜尋就能過。乙個更合理的做法是...
省選模擬 19 09 11
ps.博主趁資訊課摸魚考的暴零模擬 看門人憑感覺就知道是長鏈剖分,將路徑查分一下,dis u di sv 2 dis lc adis u dis v 2 dis disu disv 2 disl ca 維護fu,if fu,i 表示u的子樹,深度為 i 的點的 dis disdi s最大值 考慮如何...
省選模擬96
容易發現當 k 3 時無解。然後容易證明當 k 3 時,只有 m 3 才是有解的。然後直接做不好做,考慮欽定然後容斥出合法方案。對於 k 3 列舉乙個點,然後計算另乙個的方案數。其他情況類似,欽定滿足條件的角,然後容斥。然後對於每乙個 o n 的式子用組合恒等式大力化簡就可以做到 o 1 了。考慮每...