CF 1436 E 線段樹+思維
啊啊啊啊啊 ~~ 我好菜
這道題題意大概是:
求這個序列 任意連續子序列的mex 的mex。
怎麼求呢?
還好,, 有一點點想法。
從小到大列舉答案是誰,判斷它成不成立,
如何判斷呢?
假設列舉的是 x ,如果隨便一個區間中沒有 x ,並且包含 1 ~ x - 1。
那麼這個值肯定可以當答案。
然後 問題就是 怎麼判斷 隨便一個區間中沒有 x ,並且包含 1 ~ x - 1 是否成立。
剛開始想的 把x 不在的區間放到vector中,然後 遍歷一下,在主席樹上找這個區間中包不包含1~x - 1.然後突然發現主席樹好像不能這樣找,
於是查題解
差不多就是這樣的思路。
最後判斷那個條件就相當於 從前往後把這個值出現最晚的位置加到線段樹中。查詢1~i - 1 出現的最前面的位置 是否在上一個a[i] 後面。
可能有點繞。。 但是看程式碼就一目瞭然。。
程式碼:
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <stack>
#include <map>
#include <bitset>
#include <math.h>
#include <set>
#include <unordered_set>
#include <climits>
using namespace std;
typedef long long ll;
typedef pair<int,ll> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef unsigned long long ull;
typedef unordered_set<int>::iterator sit;
#define st first
#define sd second
#define mkp make_pair
#define pb push_back
void tempwj(){freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){a %= mod;ll ans = 1;while(b > 0){if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct cmp{bool operator()(const pii & a, const pii & b){return a.second > b.second;}};
int lb(int x){return x & -x;}
// friend bool operator < (Node a,Node b) 閲嶈澆
// 8388607
const int inf = INT_MAX;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
const int maxn = 2e5 + 5;
const int M = 8388607;
struct Node
{
int l,r,num;
}node[maxn << 2];
void build(int l,int r,int no)
{
node[no].l = l;
node[no].r = r;
node[no].num = 0;
if(l == r)
return;
int mid = l + r >> 1;
build(l,mid,no<<1);
build(mid + 1,r,no<<1|1);
}
void update(int pos,int no,int num)
{
if(node[no].l == node[no].r)
{
node[no].num = num;
return;
}
int mid = node[no].l + node[no].r >> 1;
if(pos <= mid)
update(pos,no<<1,num);
else
update(pos,no<<1|1,num);
node[no].num = min(node[no<<1].num,node[no<<1|1].num);
}
int query(int l,int r,int no)
{
if(node[no].l > r || node[no].r < l)
return inf;
if(node[no].l >= l && node[no].r <= r)
{
return node[no].num;
}
return min(query(l,r,no<<1),query(l,r,no<<1|1));
}
int a[maxn];
int per[maxn];
int ans[maxn];
int main()
{
int n;
scanf("%d",&n);
int f = 1;
for (int i = 1;i <= n; i ++ )
{
scanf("%d",&a[i]);
if(a[i] > 1)
f =0;
}
if(f)
{
printf("1\n");
return 0;
}
build(1,n,1);
for (int i = 1; i <= n; i ++ )
{
update(a[i],1,i);
int x = query(1,a[i] - 1,1); // 查詢之前的數出現的最前面的
if(x > per[a[i]])
{
ans[a[i]] = 1;
}
per[a[i]] = i;
}
for (int i = 1;i <= n; i ++ )
{
int x = query(1,i - 1,1);
if(x > per[i])
ans[i] = 1;
// printf("%d %d %d\n",x,per[])
}
// printf("%d %d\n",query(1,n - 1,1),per[n]);
for (int i = 1; i <= n; i ++ )
{
if(ans[i] == 0)
{
printf("%d\n",i);
return 0;
}
}
int s = query(1,n,1);
if(s > 0)
printf("%d\n",n + 2);
else
printf("%d\n",n + 1);
}
相關文章
- CF580E Kefa and Watch (線段樹維護雜湊)
- CF EDU165-E-序列問題,線段樹
- CF940E Cashback 線段樹優化DP優化
- 膜拜duyi! && CF1436E題解
- CodeForces 145 E. Lucky Queries(線段樹)
- cf1000F. One Occurrence(線段樹 set)
- 山海經:線段樹維護最大子段和
- CF 1805 D. A Wide, Wide Graph (*1800) 思維 + 樹的直徑IDE
- 線段樹維護區間等差數列
- 線段樹
- 線~段~樹
- 線段樹最佳化 DP & CF833B The Bakery 題解
- 01 線段樹
- 線段樹--RMQMQ
- 【模版】線段樹
- 線段樹模板
- 線段樹 hate it
- CF 1978 D. Elections (*1600) 思維
- CF 1971 G. XOUR (*1700) 思維
- CF1902E. Collapsing Strings-LCP、字典樹
- ut.cpp 最大線段並減線段交 [線段樹]
- 李超線段樹
- 線段樹進階
- 權值線段樹
- 線段樹筆記筆記
- Segment Tree(線段樹)
- 線段樹入門
- CF538B Quasi Binary 思維題
- 洛谷題單指南-線段樹-P3373 【模板】線段樹 2
- CF 1527 E
- CF 1029E Tree with Small Distances 樹形DP or 貪心
- 逆向思維_cf927_C. LR-remaindersREMAI
- 8.9 線段樹板子+三分補題+三維的bfs
- 懶標記線段樹
- 可持久化線段樹持久化
- 線段樹(超詳解)
- 線段樹 transformation——hdu 4578ORM
- 深入理解線段樹