UOJ637 数据结构 - 扫描线、线段树


题意

给定数列 \(\{a_n\}\)\(m\) 次询问若将 \(a_{l_i},a_{l_i+1},\dots,a_{r_i}\) 这些数 \(+1\),全局有多少个不同的数。询问相互独立。

题解

我是傻逼吧?

考虑一个数 \(x(1\le x\le \mathbf{n+1})\) 对哪些答案没有贡献。\(x\)\([l,r]\) 没有贡献,当且仅当:

  • \([1,l)\)\((r,n]\) 中都没有 \(x\)
  • \([l,r]\) 中没有 \(x-1\)

相当于 \(\mathcal{O}(n)\) 次矩形加。扫描线直接做就好了。

如果没过,先把所有数组都开大试试。

代码

#include 
#include 
#include 
#include 
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
#define Debug(...) fprintf(stderr,__VA_ARGS__)
typedef long long ll;
const int N=1e6+5;
int n,m,a[N],ans[N];
struct Fenwick{
	int t[N];
	void Add(int p,int k){for(;p<=n;p+=p&-p) t[p]+=k;}
	int Query(int p){int res=0;for(;p;p-=p&-p) res+=t[p]; return res;}
}bit;
struct Query{int i,l,r;} q[N];
struct Command{int p,l,r,w;} comm[N<<2];
int len=0;
void Update(int _ll,int lr,int rl,int rr){
	if(_ll>lr||rl>rr) return;
	comm[++len]={rl,_ll,lr,1},comm[++len]={rr+1,_ll,lr,-1};
}
vector occ[N];
int main(){
	#ifndef zyz
	ios::sync_with_stdio(false),cin.tie(nullptr);
	#endif
	cin>>n>>m;
	For(i,1,n) cin>>a[i],occ[a[i]].push_back(i);
	For(i,1,m) cin>>q[i].l>>q[i].r,q[i].i=i;
	sort(q+1,q+m+1,[](const Query &q1,const Query &q2){return q1.rr) R=min(R,p-1);
		}
		if(!br) Update(L,l,r,R);
	}
	sort(comm+1,comm+len+1,[](const Command &c1,const Command &c2){return c1.p