zoukankan      html  css  js  c++  java
  • 【LGR-077】洛谷 10 月月赛 I Div.1 && P6854 Tram

    题意

    • 给定一个序列,定义一个好的区间:

      1. 对于区间里出现的数(a_i)恰好出现(a_i)
      2. 区间里的数的值域连续
    • 求好的区间数量

    考虑以某个点(i)结束的好的区间的最后起始位置,然后向前拓展,发现最多拓展(n)次,并且每次拓展一定会将值域向小/大拓展至少1,考虑到从(1)一直加到(sqrt n)就会大于(n),所以说好的区间不会超过(nsqrt n)级别

    那么只需要(o(1))或者(o(log n))的复杂度内找到一个可行位置再加进答案就行

    于是从左往右,每次对当前数维护可行的区间就好

    具体的操作是,假设当前数为(x)那么找到前(x)个的位置,这中间是不能选的,以及前(x+1)(x)之前的位置也是不能选的

    所以就可以线段树,每次将不能选的位置(+1),维护区间最小值,然后在线段树上二分即可

    #include<bits/stdc++.h>
    #define For(i, a, b) for(int i = (a), en = (b); i <= en; ++i)
    #define Rof(i, a, b) for(int i = (a), en = (b); i >= en; --i)
    #define Tra(u, i) for(int i = hd[u]; ~i; i = e[i].net)
    #define cst const
    #define LL long long
    #define DD double
    #define LD long double
    #define pb push_back
    #define mp make_pair
    #define fir first
    #define sec second
    #define inf 0x3f3f3f3f
    #define Inf 0x3f3f3f3f3f3f3f3f
    #define eps 1e-12
    #define maxn 1000000
    using namespace std;
    
    int n, a[maxn + 5], as = 0, pre[maxn + 5], net[maxn + 5], to[maxn + 5], cnt[maxn + 5];
    map<int, int> ma;
    void chkmn(int &x, int y){if(x > y) x = y;}
    void chkmx(int &x, int y){if(x < y) x = y;}
    int tr[2][maxn + 5];
    void ins(int ty, int x, int y){
    	x = maxn - x + 1;
    	while(x <= maxn) ty ? chkmx(tr[ty][x], y) : chkmn(tr[ty][x], y), x += x & -x;
    }
    int que(int ty, int x){
    	x = maxn - x + 1; int asi = ty ? 0 : inf;
    	while(x) ty ? chkmx(asi, tr[ty][x]) : chkmn(asi, tr[ty][x]), x -= x & -x;
    	return asi;
    }
    struct Node{int mn, lpr;} poi[4 * maxn + 5];
    struct Tree{
    	#define ls rt << 1
    	#define rs rt << 1 | 1
    	#define mn(rt) poi[rt].mn
    	#define lpr(rt) poi[rt].lpr
    	void upd(int rt){mn(rt) = min(mn(ls), mn(rs));}
    	void mson(int rt, int x){
    		mn(rt) += x;
    		lpr(rt) += x;
    	}
    	void spr(int rt){
    		if(!lpr(rt)) return;
    		mson(ls, lpr(rt));
    		mson(rs, lpr(rt));
    		lpr(rt) = 0;
    	}
    	void mdy(int rt, int nl, int nr, int ql, int qr, int x){
    		if(ql > qr) return;
    		if(ql <= nl && qr >= nr) return mson(rt, x);
    		spr(rt);
    		int mid = nl + nr >> 1;
    		if(ql <= mid) mdy(ls, nl, mid, ql, qr, x);
    		if(qr > mid) mdy(rs, mid + 1, nr, ql, qr, x);
    		upd(rt);
    	}
    	void sol(int rt, int nl, int nr, int ql, int qr){
    		if(mn(rt)) return;
    		if(nl == nr){
    			int mn = que(0, nl), mx = que(1, nl);
    			if((mn + mx) * (mx - mn + 1) / 2 == qr - nl + 1) as++;
    			return;
    		}
    		spr(rt);
    		int mid = nl + nr >> 1;
    		if(ql <= mid) sol(ls, nl, mid, ql, qr);
    		if(qr > mid) sol(rs, mid + 1, nr, ql, qr);
    	}
    	void quee(int rt, int nl, int nr){
    		if(nl == nr) return (void)(cout << mn(rt) << " ");
    		spr(rt);
    		int mid = nl + nr >> 1;
    		quee(ls, nl, mid); quee(rs, mid + 1, nr);
    	}
    } tr1;
    
    template <class T>
    void read(T &x){
    	char ch;
    	bool ok;
    	for(ok = 0, ch = getchar(); !isdigit(ch); ch = getchar()) if(ch == '-') ok = 1;
    	for(x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
    	if(ok) x = -x;
    }
    
    void mdy(int x, int y){
    	if(!x) return;
    	if(cnt[x] > a[x]) tr1.mdy(1, 1, n, to[x] + 1, x, y), tr1.mdy(1, 1, n, 1, pre[to[x]], y);
    	else if(cnt[x] == a[x]) tr1.mdy(1, 1, n, to[x] + 1, x, y);
    	else tr1.mdy(1, 1, n, 1, x, y);
    	ins(0, x, a[x]);
    	ins(1, x, a[x]);
    	//if(x == 2) cout << que(0, x) << endl;
    }
    
    int main(){
    	//freopen("in", "r", stdin);
    	memset(tr[0], inf, sizeof tr[0]);
    	read(n);
    	For(i, 1, n){
    		read(a[i]);
    		net[pre[i] = ma[a[i]]] = i;
    		ma[a[i]] = i;
    		cnt[i] = cnt[pre[i]] + 1;
    		if(a[i] == 1) to[i] = i;
    		else if(cnt[i] > a[i]) to[i] = net[to[pre[i]]];
    		else if(cnt[i] == a[i]) to[i] = to[pre[i]];
    		else if(cnt[i] == 1) to[i] = i;
    		else to[i] = to[pre[i]];
    		mdy(pre[i], -1);
    		mdy(i, 1);
    		tr1.sol(1, 1, n, 1, i);
    		/*tr1.quee(1, 1, n);
    		puts("");*/
    	}
    	printf("%d
    ", as);
    	return 0;
    }
    
  • 相关阅读:
    2Windows程序设计 Unicode
    C语言指针与字符串(高阶篇三十二)
    C语言指针与函数(高阶篇三十三)
    1Windows程序设计 学习第一个窗口
    C语言链表实践(高阶篇三十七)
    3Windows程序设计 窗口与消息
    C语言双重指针与数组(高阶篇三十五)
    AspNetCore缓存技术
    k8s安装教程
    C# Winform 委托实现B页面给A页面赋值
  • 原文地址:https://www.cnblogs.com/lprdsb/p/13799190.html
Copyright © 2011-2022 走看看