其實就是將乙個點f拆成向左l向右r的兩個點,然後將所有點排序(不用排序也行,直接找),①選第乙個l,從後往前選第乙個不與l同乙個f的r。②選最後乙個r,從前往後選第乙個不與r同乙個f的l。①②答案中的最大值即為兩點之間的最遠距離。
證明如下:
0;}數學方法:
把01看成a+b個點。
設s=a+b,x=最少要翻轉次數,ti=點i翻轉兩次的次數。 ①(
xk−a
)/2=
∑ni=
1ti ∴xk-a≥0且為偶數
②假設各點ti達到最大。
點i為1則ti=x/2
點i為0則ti=(x-1)/2 得到(
xk−a
)/2≤
a∗((
x−1)
/2)+
b∗(x
/2)
答案不超過s,列舉判斷是否符合①②條件,符合則可行。找不到的輸出-1。
#include
#include
#include
#include
typedef
long
long ll;
using
namespace
std;
int ng;
long
long a,b,k,s;
int main()
return
0;}
可以得知,depx=depxfather+1。
如何找出x的父親呢?
根據排序二叉樹的性質,二叉排序樹的中序遍歷的序列有序。假設插入x後,在二叉樹的中序遍歷中,x與xfather一定是相鄰的。
那麼與x相鄰的有兩個,哪乙個才是xfather?其實比較一下兩點插入的時間,時間晚的一定是xfather。與x相鄰表示乙個是xfather,另乙個一定不在xfather這棵子樹中(如果在,則一定為x的兒子,但還沒插入,僅此一種情況)而是xfather的father(由性質可得),所以時間晚的就是xfather。
直接做可以用線段樹或splay過掉。
但還有一種更優的做法。
逆向思維,從後往前做,對於點i,1->i的序列是有序的,直接可得距離i最近的兩個點,求出ifather。然後將i點刪除,仍需維護1->i-1有序。可以用鍊錶,刪除點i等於
r[l[i]]=r[i]; l[r[i]]=l[i];
#include
#include
#include
#define imax(a,b) ((a>b)?(a):(b))
typedef
long
long ll;
using
namespace
std;
const
int n=301000;
int n,d[n+10],tn[n+10],l[n+10],r[n+10];
int son[n+10][5],f[n+10],fa[n+10];
long
long ans;
int main()
ans=0ll; f[1]=0;
for(int i=2;i<=n;i++) f[i]=f[fa[i]]+1;
for(int i=1;i<=n;i++) printf("%lld\n",(ans+=f[i]));
return
0;}
NOIP2017提高組模擬賽4 (總結)
這道題就是很簡單的bfs,可以觀察到n變化到m是近似成倍增長的。其實從最小到最大的變化也就只有30次而已。include include include typedef long long ll using namespace std const int maxl 100 const int oo ...
NOIP2017提高組 模擬賽21(總結)
題目描述 解題思路 問題轉化為有多少個 l,r 使得a的l r這個區間乘起來是k的倍數。k 的時間分解k的質因數。列舉l,可以發現r具有單調性,也就是若 l,r 合法,那麼 l,r 1 也合法。用尺取法就可以解決。時間複雜度 o 2n k include include using namespac...
NOIP2017提高組 模擬賽 26(總結)
題目描述 解題思路 構造法 假設現在有m個點,刪除乙個點,剩下的m 1個點都已經確定,那麼刪除的這個點應該染什麼顏色。假如這個點所在的行的點數為奇數,那麼點的染色只與它所在的列有關 若列有偶數個點,那麼這個點的顏色就可以確定了,哪種顏色少選哪種。否則隨便選 假如這個點所在的列的點數為奇數,與上面類似...