第一行n
第二行n個數
答案3
0 1 3
n<=
200000 a
i<=109
50分暴力明顯,用標記陣列隨便yy
但是你可能在想要離散化,其實凡是大於n的都直接等於n就行了,mex最大就是n
想:如果知道[1,n]的mex,能不能求到[2,n]
顯然mex[1,i]是單調遞增的,當第乙個數被刪掉時,如果後面原來比這個數大,並且在下乙個數出現之前,那就變成這個數
區間修改就可以用線段樹了
加上乙個線段樹上二分
線段樹初始化為mex[1,1],mex[1,2],mex[1,3]……一次修改變成mex[2,2],mex[2,3]……
修改n-1次,每次求和就行了
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define n 201000
#define ll long long
using namespace std;
int n,a[n],tot=0,bz[n],next[n];
ll ans=0;
struct note;
note t[n*25];
void down(int v,int i,int j)
void insert(int v,int i,int j,int
x,int
y,ll z)
intm=(i+j)/2;down(v,i,j);
if(y
<=m) insert(v*2,i,m,x,y,z);
else
if(x>m) insert(v*2+1,m+1,j,x,y,z);
else insert(v*2,i,m,x,m,z),insert(v*2+1,m+1,j,m+1,y,z);
t[v].m=max(t[v*2].m,t[v*2+1].m);t[v].h=t[v*2].h+t[v*2+1].h;
}int find(int v,int i,int j,ll x)
intm=(i+j)/2;down(v,i,j);
if(t[v*2].m>x) return find(v*2,i,m,x);
else
return find(v*2+1,m+1,j,x);
}int main()
fo(i,1,n) next[i]=(next[i]==0)?n+1:next[i];
fo(i,1,n-1)
printf("%lld",ans);
}
NOIP2016提高A組8 11 錢倉
發現,一定有乙個點作為起點,所有的路徑都不經過這個起點。接著貪心求答案,如果c i 1 將其中ci 1個錢往後 鋪 易證x 2 y2 x y 2 那麼維護乙個佇列,先進先出,就能保證最小。include include include include include include include ...
NOIP2016提高A組8 11 錢倉
發現,一定有乙個點作為起點,所有的路徑都不經過這個起點。接著貪心求答案,如果 c i 1 將其中 c i 1 個錢往後 鋪 易證 x 2 y 2 x y 2 那麼維護乙個佇列,先進先出,就能保證最小。include include include include include include in...
NOIP2016提高A組8 11 自然數
n 求出mex 1,i 1 i n 雖然0 ai 10 9,但只有n個數,所以mex一定小於等於n for long long j 1 j n j 顯然mex是單調不下降的,接著用線段樹維護mex。如果刪掉a i 從下乙個mex比a i 大的位置到下乙個a i 的位置之前的mex都會改變,都會變成a...