hdu 4747 Mex 線段樹區間更新

2021-06-26 07:16:02 字數 1705 閱讀 6321

有大神部落格在。

mex有兩個特徵,乙個是最小,乙個是不在集合中

首先可以看出mex是遞增的

刪掉乙個數a[i]對mex[l, r](r對l>i的影響是,a[i]不在集合中了,在a[i]下次出現之前,那些大於a[i]的mex[j]都可以被減小至a[i]

話說線段樹區間更新每次都寫挫

一開始pushdown()沒有加上對sumv,maxv的修改

#include #include #include #include #include #include #include #include #include using namespace std;

#define inf 1e9

#define maxn 200000

#define rep(i,x,y) for(int i=x;i<=y;i++)

#define mset(x) memset(x,0,sizeof(x))

typedef __int64 ll;

const int maxnode = maxn * 4;

int n;

int a[maxn];

int mex[maxn];

sets;

mapmp;

int next[maxn];//a[i]下一次出現的位置next[i]

ll sumv[maxnode], setv[maxnode], maxv[maxnode];

void init()

void pushup(int o)

void pushdown(int o, int l, int r)

}void build(int o, int l, int r)

int mid = l+(r-l)/2, lc = 2*o, rc = 2*o+1;

build(lc, l, mid);

build(rc, mid+1, r);

pushup(o);

}int x1, x2, v;

void update(int o, int l, int r)

int mid = l+(r-l)/2, lc = 2*o, rc = 2*o+1;

pushdown(o, l, r);

if(x1<=mid) update(lc, l, mid);

if(x2>mid) update(rc, mid+1, r);

pushup(o);

}//找mex[j]>=a[i]的第乙個數j

//由於mex是遞增的,可以二分查詢

//線段樹上進行二分查詢可以用maxv標記

int res;

void query(int o, int l, int r)

int mid = l+(r-l)/2, lc = 2*o, rc = 2*o+1;

pushdown(o, l, r);

if(maxv[lc]>v) query(lc, l, mid);

else query(rc, mid+1, r);

}int main()

build(1,1,n);

rep(i,1,n)

}ll ans=0;

rep(i,1,n)

x1=i, x2=i, v=0, update(1, 1, n);

}printf("%i64d\n", ans);

}return 0;

}

hdu 4747 mex 線段樹 思維

題意 我們定義mex l,r 表示乙個序列a l a r 中沒有出現過得最小的非負整數,然後我們給出乙個長度為n的序列,求他所有的連續的子串行的mex l,r 的和。思路 首先因為n的最大值就是2 10 5 所有我們字需要考慮200000之內的數就好了,然後o 2 n 可以求出 1,1 1,2 1,...

區間MEX 線段樹維護mex陣列

問題描述 給你乙個長度為n的數列,元素編號1到n,第i個元素值為ai。現在有m個形如 l,r 的提問,你需要回答出區間 l,r 的mex值。即求出區間 l,r 中沒有出現過的最小的非負整數。輸入格式 第一行,兩個整數n和m 第二行,n個空格間隔的整數,表示數列a 接下來m行,每行兩個整數l,r,表示...

mex(線段樹 離散化)

題目描述 給你乙個無限長的陣列,初始的時候都為0,有3種操作 操作1是把給定區間 l,r l,r l,r 設為1,操作2是把給定區間 l,r l,r l,r 設為0,操作3把給定區間 l,r l,r l,r 0,1反轉。l r 一共n個操作,每次操作後要輸出最小位置的0。l,r 題解 l r 經過分...