傳送門
題目
給乙個1到n的排列,詢問是否存在1<=p1=3),
使得ap1,ap2,ap3,…aplen是乙個等差序列。
input
輸入的第一行包含乙個整數t,表示組數。
下接t組資料,每組第一行乙個整數n,每組第二行為乙個1到n的排列,數字兩兩之間用空格隔開。
n<=10000,t<=7
output
對於每組資料,如果存在乙個等差子串行,則輸出一行「y」,否則輸出一行「n」。
分析
比較燒腦的題目。首先我們知道這少長度為三則只要存在長度為三的即可,所以我們只找長度為三的等差子串行。假設三個數分別為x-l,x,x+l,則以x為中心,另外兩個數一定不再x的同一側,即如果在插入x之前x-l和x+l都插入過或者都沒插入過就是不行的。在想明白這點之後我們再考慮如何實現:
我們建立一棵權值線段樹,按讀入的數依次插入線段樹中,每一次在插入的同時將小於這個值的插入過的值正著雜湊一遍並將大於這個值的插入過的值反著雜湊一邊,我們知道如果這兩個雜湊值相等,則關於這個x為中心是不可能存在等差子串行的,而如果不相等則存在,所以這道題就得到解決啦。
**
#include#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define li unsigned long longli d[
5][440000],up[110000
]; inline
intread()
while(s>='
0'&&s<='9')
return x*f;
}inline li q(
int le,int ri,int x,int y,int k,int
wh)
int mid=(le+ri)>>1
;
if(mid>=y)return q(le,mid,x,y,k,wh<<1
);
else
if(midreturn q(mid+1,ri,x,y,k,wh<<1|1
);
else
else
}}inline
void update(int le,int ri,int pl,int
wh)
int mid=(le+ri)>>1
;
if(mid>=pl)update(le,mid,pl,wh<<1
);
else update(mid+1,ri,pl,wh<<1|1
); d[
0][wh]=d[0][wh<<1]*up[ri-mid]+d[0][wh<<1|1
]; d[
1][wh]=d[1][wh<<1|1]*up[mid-le+1]+d[1][wh<<1];}
intmain()}}
if(ok)puts("y"
);
else puts("n"
); }
return0;
}
BZOJ2124 等差子串行
挺厲害的題 我們考慮當前加入了第i個數,為x,那麼我們可以維護一下哪個數出現過,出現過為1,沒出現為0,那麼加入x的時候我們只需要判斷以x為中心的極長子串是否是回文串即可 用乙個樹狀陣列維護兩個方向的雜湊值即可 include include include include include incl...
bzoj 2124 等差子串行
description 給乙個1到n的排列,詢問是否存在1 p1 p2 p3 p4 p5 plen n len 3 使得ap1,ap2,ap3,aplen是乙個等差序列。input 輸入的第一行包含乙個整數t,表示組數。下接t組資料,每組第一行乙個整數n,每組第二行為乙個1到n的排列,數字兩兩之間用...
BZOJ 2124 等差子串行
給乙個1到n的排列,詢問是否存在 3 plen 使得ap1,ap2,ap3,aplen是乙個等差序列。輸入的第一行包含乙個整數t,表示組數。下接t組資料,每組第一行乙個整數n,每組第二行為乙個1到n的排列,數字兩兩之間用空格隔開。對於每組資料,如果存在乙個等差子串行,則輸出一行 y 否則輸出一行 n...