<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【做題記錄】2025暑假-數(shù)據(jù)結(jié)構(gòu)專題

      A. Closest Equals

      首先給每個位置求出它到上一次出現(xiàn)的距離,將這記為一條線段。我們發(fā)現(xiàn),有效的線段,其隨著左端點的增長,右端點必然是增長的。因為如果有一條大線段包含了小線段,大線段必然是沒用的。于是我們便可以二分出查詢的線段區(qū)間,ST 表求出最小值即可。

      Code
      #include<bits/stdc++.h>
      #define il inline
      #define lwrb lower_bound
      #define uprb upper_bound
      using namespace std;
      namespace asbt{
      const int maxn=5e5+5;
      int n,m,cnt,ll[maxn],rr[maxn],Log[maxn],st[maxn][22];
      map<int,int> pos;
      il int query(int l,int r){
      	if(l>r){
      		return -1;
      	}
      	int p=Log[r-l+1];
      	return min(st[l][p],st[r-(1<<p)+1][p]);
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=1,j,x;i<=n;i++){
      		cin>>x;
      		j=pos[x];
      		if(j>ll[cnt]){
      			ll[++cnt]=j,rr[cnt]=i;
      		}
      		pos[x]=i;
      	}
      	for(int i=2;i<=cnt;i++){
      		Log[i]=Log[i>>1]+1;
      	}
      	for(int i=1;i<=cnt;i++){
      		st[i][0]=rr[i]-ll[i];
      	}
      	for(int j=1;j<=Log[cnt];j++){
      		for(int i=1;i+(1<<j)-1<=cnt;i++){
      			st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
      		}
      	}
      	while(m--){
      		int l,r;
      		cin>>l>>r;
      		cout<<query(lwrb(ll+1,ll+cnt+1,l)-ll,uprb(rr+1,rr+cnt+1,r)-rr-1)<<"\n";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      B. Fibonacci-ish II

      考慮莫隊,用權(quán)值線段樹維護矩陣。當(dāng)新加入一個數(shù)時,要給它后面的數(shù)全都乘上 \(\begin{bmatrix}0&1\\1&1\end{bmatrix}\);刪除時,要給后面都乘上逆矩陣。時間復(fù)雜度 \(O(n\sqrt{n}\log n)\),比較卡常,注意傳參的時間消耗。卡正解常放暴力過的出題人是屑

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define lwrb lower_bound
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace IO{
      	const int bufsz=1<<20;
      	char ibuf[bufsz],*p1=ibuf,*p2=ibuf;
      	#define getchar() (p1==p2&&(p2=(p1=ibuf)+fread(ibuf,1,bufsz,stdin),p1==p2)?EOF:*p1++)
      	il int read(){
      		char ch=getchar();
      		while(ch<'0'||ch>'9'){
      			ch=getchar();
      		}
      		int x=0;
      		while(ch>='0'&&ch<='9'){
      			x=(x<<1)+(x<<3)+(ch^48);
      			ch=getchar();
      		}
      		return x;
      	}
      	#undef getchar
      }
      using IO::read;
      const int maxn=3e4+5,bln=173;
      int n,m,mod,a[maxn],lsh[maxn],tot,sz[maxn<<2],tag[maxn<<2],cnt[maxn],bel[maxn],ans[maxn];
      struct node{
      	int l,r,id;
      	il bool operator<(const node &x)const{
      		return (bel[l]^bel[x.l])?l<x.l:bel[l]&1?r>x.r:r<x.r;
      	}
      }wt[maxn];
      struct juz{
      	int a00,a01,a10,a11;
      	juz(int a00=0,int a01=0,int a10=0,int a11=0):a00(a00),a01(a01),a10(a10),a11(a11){}
      	il juz operator+(const juz &x)const{
      		#define pls(x,y) x+y<mod?x+y:x+y-mod
      		return juz(pls(a00,x.a00),pls(a01,x.a01),pls(a10,x.a10),pls(a11,x.a11));
      		#undef pls
      	}
      	il juz operator*(const juz &x)const{
      		int t1=a00*x.a00+a01*x.a10,t2=a00*x.a01+a01*x.a11,t3=a10*x.a00+a11*x.a10,t4=a10*x.a01+a11*x.a11;
      		#define qum(x) x<mod?x:x%mod
      		return juz(qum(t1),qum(t2),qum(t3),qum(t4));
      		#undef qum
      	}
      	il bool operator!=(const juz &x)const{
      		return (a00^x.a00)||(a01^x.a01)||(a10^x.a10)||(a11^x.a11);
      	}
      }A,B,I,SA[maxn],SB[maxn],f[maxn],sum[maxn<<2];
      il void pushup(int id){
      	sum[id]=sum[lid]+sum[rid];
      	sz[id]=sz[lid]+sz[rid];
      }
      il void pushtag(int id,int v){
      	tag[id]+=v;
      	juz t=v>0?SA[v]:SB[-v];
      	sum[id]=sum[id]*t;
      }
      il void pushdown(int id){
      	if(tag[id]){
      		pushtag(lid,tag[id]);
      		pushtag(rid,tag[id]);
      		tag[id]=0;
      	}
      }
      il void mul(int id,int L,int R,int l,int r,int v){
      	if(L>=l&&R<=r){
      		pushtag(id,v);
      		return ;
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		mul(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		mul(rid,mid+1,R,l,r,v);
      	}
      	pushup(id);
      }
      il void upd(int id,int l,int r,int p,int v,int rk){
      	if(l==r){
      		sum[id]=f[rk+1]*juz(v,0,0,v),sz[id]^=1;
      		return ;
      	}
      	pushdown(id);
      	int mid=(l+r)>>1;
      	if(p<=mid){
      		upd(lid,l,mid,p,v,rk);
      	}
      	else{
      		upd(rid,mid+1,r,p,v,sz[lid]+rk);
      	}
      	pushup(id);
      }
      il void add(int p){
      	if(cnt[p]++==0){
      		upd(1,1,tot,p,lsh[p],0);
      		if(p<tot){
      			mul(1,1,tot,p+1,tot,1);
      		}
      	}
      }
      il void del(int p){
      	if(--cnt[p]==0){
      		upd(1,1,tot,p,0,0);
      		if(p<tot){
      			mul(1,1,tot,p+1,tot,-1);
      		}
      	}
      }
      int main(){
      //	freopen("B.in","r",stdin);
      //	freopen("my.out","w",stdout);
      	n=read(),mod=read();
      	A=juz(0,1,1,1),B=juz(mod-1,1,1,0),I=juz(1,0,0,1);
      	SA[0]=SB[0]=I;
      	for(int i=1;i<=n;i++){
      		a[i]=read();
      		lsh[++tot]=a[i];
      		bel[i]=i/bln;
      		SA[i]=SA[i-1]*A;
      		SB[i]=SB[i-1]*B;
      	}
      	sort(lsh+1,lsh+tot+1);
      	tot=unique(lsh+1,lsh+tot+1)-lsh-1;
      	for(int i=1;i<=n;i++){
      		a[i]=lwrb(lsh+1,lsh+tot+1,a[i])-lsh;
      	}
      	for(int i=1;i<=tot;i++){
      		lsh[i]%=mod;
      	}
      	f[1]=juz(0,1);
      	for(int i=2;i<=n;i++){
      		f[i]=f[i-1]*A;
      	}
      	m=read();
      	for(int i=1;i<=m;i++){
      		wt[i].l=read(),wt[i].r=read(),wt[i].id=i;
      	}
      	sort(wt+1,wt+m+1);
      	int l=1,r=0;
      	for(int i=1;i<=m;i++){
      		while(l>wt[i].l){
      			add(a[--l]);
      		}
      		while(r<wt[i].r){
      			add(a[++r]);
      		}
      		while(l<wt[i].l){
      			del(a[l++]);
      		}
      		while(r>wt[i].r){
      			del(a[r--]);
      		}
      		ans[wt[i].id]=sum[1].a01;
      	}
      	for(int i=1;i<=m;i++){
      		printf("%d\n",ans[i]);
      	}
      //	cerr<<clock()<<"\n";
      	return 0;
      }
      /*
      5 1000
      1 5 2 3 2 
      5
      4 5
      2 4
      1 4
      1 3
      4 4
      5
      15
      24
      13
      3
      */
      

      C. Sasha and Array

      沿用上一道題的思路,仍然用線段樹維護矩陣即可。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      const int maxn=1e5+5,mod=1e9+7;
      int n,m,a[maxn];
      struct juz{
      	int mat[2][2];
      	juz(){
      		mat[0][0]=mat[0][1]=mat[1][0]=mat[1][1]=0;
      	}
      	il int*operator[](int x){
      		return mat[x];
      	}
      	il juz operator+(juz x)const{
      		juz res;
      		for(int i=0;i<=1;i++){
      			for(int j=0;j<=1;j++){
      				res[i][j]=(mat[i][j]+x[i][j])%mod;
      			}
      		}
      		return res;
      	}
      	il juz operator*(juz x)const{
      		juz res;
      		for(int i=0;i<=1;i++){
      			for(int j=0;j<=1;j++){
      				for(int k=0;k<=1;k++){
      					(res[i][j]+=mat[i][k]*1ll*x[k][j]%mod)%=mod;
      				}
      			}
      		}
      		return res;
      	}
      	il bool operator!=(juz x)const{
      		for(int i=0;i<=1;i++){
      			for(int j=0;j<=1;j++){
      				if(mat[i][j]!=x[i][j]){
      					return 1;
      				}
      			}
      		}
      		return 0;
      	}
      }A,I,sum[maxn<<2],tag[maxn<<2];
      il juz qpow(juz x,int y){
      	juz res;
      	res[0][0]=res[1][1]=1;
      	for(;y;y>>=1,x=x*x){
      		if(y&1){
      			res=res*x;
      		}
      	}
      	return res;
      }
      il void pushup(int id){
      	sum[id]=sum[lid]+sum[rid];
      }
      il void pushtag(int id,juz v){
      	tag[id]=tag[id]*v;
      	sum[id]=sum[id]*v;
      }
      il void pushdown(int id){
      	if(tag[id]!=I){
      		pushtag(lid,tag[id]);
      		pushtag(rid,tag[id]);
      		tag[id]=I;
      	}
      }
      il void build(int id,int l,int r){
      	tag[id]=I;
      	if(l==r){
      		sum[id]=qpow(A,a[l]);
      		return ;
      	}
      	int mid=(l+r)>>1;
      	build(lid,l,mid);
      	build(rid,mid+1,r);
      	pushup(id);
      }
      il void mul(int id,int L,int R,int l,int r,juz v){
      	if(L>=l&&R<=r){
      		pushtag(id,v);
      		return ;
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		mul(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		mul(rid,mid+1,R,l,r,v);
      	}
      	pushup(id);
      }
      il juz query(int id,int L,int R,int l,int r){
      	if(L>=l&&R<=r){
      		return sum[id];
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(r<=mid){
      		return query(lid,L,mid,l,r);
      	}
      	if(l>mid){
      		return query(rid,mid+1,R,l,r);
      	}
      	return query(lid,L,mid,l,r)+query(rid,mid+1,R,l,r);
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	A[0][1]=A[1][0]=A[1][1]=I[0][0]=I[1][1]=1;
      	cin>>n>>m;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      	}
      	build(1,1,n);
      	while(m--){
      		int opt,l,r,x;
      		cin>>opt>>l>>r;
      		if(opt==1){
      			cin>>x;
      			mul(1,1,n,l,r,qpow(A,x));
      		}
      		else{
      			cout<<query(1,1,n,l,r)[0][1]<<"\n";
      		}
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      D. New Year Tree

      發(fā)現(xiàn) \(c\) 很小,于是考慮開 long long 狀壓,dfn+ 線段樹即可。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pb push_back
      #define popcntll __builtin_popcountll
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      const int maxn=4e5+5;
      int n,m,cnt,a[maxn],L[maxn],R[maxn],stk[maxn];
      ll sum[maxn<<2],tag[maxn<<2];
      vector<int> e[maxn];
      il void dfs(int u,int fa){
      	stk[++cnt]=u,L[u]=cnt;
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		dfs(v,u);
      	}
      	R[u]=cnt;
      }
      il void pushup(int id){
      	sum[id]=sum[lid]|sum[rid];
      }
      il void pushtag(int id,ll v){
      	sum[id]=tag[id]=v;
      }
      il void pushdown(int id){
      	if(tag[id]){
      		pushtag(lid,tag[id]);
      		pushtag(rid,tag[id]);
      		tag[id]=0;
      	}
      }
      il void build(int id,int l,int r){
      	if(l==r){
      		sum[id]=1ll<<a[stk[l]];
      		return ;
      	}
      	int mid=(l+r)>>1;
      	build(lid,l,mid);
      	build(rid,mid+1,r);
      	pushup(id);
      }
      il void upd(int id,int L,int R,int l,int r,ll v){
      	if(L>=l&&R<=r){
      		pushtag(id,v);
      		return ;
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		upd(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		upd(rid,mid+1,R,l,r,v);
      	}
      	pushup(id);
      }
      il ll query(int id,int L,int R,int l,int r){
      	if(L>=l&&R<=r){
      		return sum[id];
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	ll res=0;
      	if(l<=mid){
      		res|=query(lid,L,mid,l,r);
      	}
      	if(r>mid){
      		res|=query(rid,mid+1,R,l,r);
      	}
      	return res;
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n>>m;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      	}
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      	}
      	dfs(1,0),build(1,1,n);
      	while(m--){
      		int opt,u,x;
      		cin>>opt>>u;
      		if(opt==1){
      			cin>>x;
      			upd(1,1,n,L[u],R[u],1ll<<x);
      		}
      		else{
      			cout<<popcntll(query(1,1,n,L[u],R[u]))<<"\n";
      		}
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      E. Lucky Array

      首先將所有 lucky numbers 都打出來,發(fā)現(xiàn) \(1e4\) 以內(nèi)只有 \(30\) 個??紤]線段樹,在每個下標(biāo)存儲該位置與第一個 \(\ge\) 它的幸運數(shù)之差,維護區(qū)間最小值及個數(shù),于是區(qū)間修改就成區(qū)間減了。當(dāng)有的數(shù)被減成了負數(shù),那就把這個位置暴力更新出來。每個位置最多更新 \(30\) 次,于是時間復(fù)雜度 \(O(30n\log n)\)。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define lwrb lower_bound
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      const int maxn=1e5+5,inf=1e9;
      int n,m,cnt,a[maxn],b[maxn],tag[maxn<<2]; 
      struct seg{
      	int val,cnt;
      	seg(int val=0,int cnt=0):val(val),cnt(cnt){}
      	il seg operator+(const seg &x)const{
      		if(val==x.val){
      			return seg(val,cnt+x.cnt);
      		}
      		return val<x.val?*this:x;
      	}
      }tr[maxn<<2];
      il void pushup(int id){
      	tr[id]=tr[lid]+tr[rid];
      }
      il void pushtag(int id,int v){
      	tag[id]+=v,tr[id].val+=v;
      }
      il void pushdown(int id){
      	if(tag[id]){
      		pushtag(lid,tag[id]);
      		pushtag(rid,tag[id]);
      		tag[id]=0;
      	}
      }
      il void reset(int id,int &x){
      	int t=*lwrb(b+1,b+cnt+1,x);
      	tr[id]=seg(t-x,1),x=t;
      }
      il void build(int id,int l,int r){
      	if(l==r){
      		reset(id,a[l]);
      		return ;
      	}
      	int mid=(l+r)>>1;
      	build(lid,l,mid);
      	build(rid,mid+1,r);
      	pushup(id);
      }
      il void add(int id,int L,int R,int l,int r,int v){
      	if(L>=l&&R<=r){
      		pushtag(id,v);
      		return ;
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		add(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		add(rid,mid+1,R,l,r,v);
      	}
      	pushup(id);
      }
      il void upd(int id,int l,int r){
      	if(l==r){
      		a[l]-=tr[id].val;
      		reset(id,a[l]);
      		return ;
      	}
      	pushdown(id);
      	int mid=(l+r)>>1;
      	if(tr[lid].val<0){
      		upd(lid,l,mid);
      	}
      	else{
      		upd(rid,mid+1,r);
      	}
      	pushup(id);
      }
      il seg query(int id,int L,int R,int l,int r){
      	if(L>=l&&R<=r){
      		return tr[id];
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(r<=mid){
      		return query(lid,L,mid,l,r);
      	}
      	if(l>mid){
      		return query(rid,mid+1,R,l,r);
      	}
      	return query(lid,L,mid,l,r)+query(rid,mid+1,R,l,r);
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	for(int i=1,x;i<=1e4;i++){
      		x=i;
      		while(x){
      			if(x%10!=4&&x%10!=7){
      				goto togo;
      			}
      			x/=10;
      		}
      		b[++cnt]=i;
      		togo:;
      	}
      	b[++cnt]=inf;
      //	cout<<cnt<<"\n";
      //	for(int i=1;i<=cnt;i++){
      //		cout<<b[i]<<"\n";
      //	}
      	cin>>n>>m;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      	}
      	build(1,1,n);
      	while(m--){
      		string opt;
      		int l,r,x;
      		cin>>opt>>l>>r;
      		if(opt[0]=='a'){
      			cin>>x;
      			add(1,1,n,l,r,-x);
      			while(tr[1].val<0){
      				upd(1,1,n);
      			}
      		}
      		else{
      			seg ans=query(1,1,n,l,r);
      			cout<<(ans.val?0:ans.cnt)<<"\n";
      		}
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      F. Escape Through Leaf

      \(dp_u\) 表示 \(u\) 的答案,于是有方程:\(dp_u=\min_{v\in subtree_u}\{dp_v+b_v\times a_u\}\),顯然的李超線段樹。由于要用子樹中的點更新答案,所以需要線段樹合并。根據(jù)勢能分析時間復(fù)雜度 \(O(n\log n)\)。通過精細實現(xiàn)可以做到空間線性。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pb push_back
      using namespace std;
      namespace asbt{
      const int maxn=1e5+5;
      const ll inf=1e18;
      int n,cnt,rt[maxn],ls[maxn],rs[maxn],tr[maxn];
      ll a[maxn],b[maxn],dp[maxn];
      vector<int> e[maxn];
      struct{
      	ll k,b;
      	il ll calc(int x){
      		return k*x+b;
      	}
      }xd[maxn];
      il void insert(int &p,int l,int r,int q){
      	if(!p){
      		p=q;
      		ls[p]=rs[p]=0;
      		return ;
      	}
      	ll lp=xd[tr[p]].calc(l),rp=xd[tr[p]].calc(r);
      	ll lq=xd[tr[q]].calc(l),rq=xd[tr[q]].calc(r);
      	if(lp>=lq&&rp>=rq){
      		swap(tr[p],tr[q]);
      		swap(lp,lq),swap(rp,rq);
      	}
      	if(lp<=lq&&rp<=rq){
      		return ;
      	}
      	int mid=(l+r)>>1;
      	if(xd[tr[p]].calc(mid)>xd[tr[q]].calc(mid)){
      		swap(tr[p],tr[q]);
      		swap(lp,lq),swap(rp,rq);
      	}
      	if(lq<lp){
      		insert(ls[p],l,mid,q);
      	}
      	else{
      		insert(rs[p],mid+1,r,q);
      	}
      }
      il int merge(int p,int q,int l,int r){
      	if(!p||!q){
      		return p+q;
      	}
      	if(l==r){
      		return xd[tr[p]].calc(l)<xd[tr[q]].calc(l)?p:q;
      	}
      	int mid=(l+r)>>1;
      	ls[p]=merge(ls[p],ls[q],l,mid);
      	rs[p]=merge(rs[p],rs[q],mid+1,r);
      	insert(p,l,r,q);
      	return p;
      }
      il ll query(int id,int l,int r,int p){
      	if(!id){
      		return inf;
      	}
      	ll res=xd[tr[id]].calc(p);
      	if(l==r){
      		return res;
      	}
      	int mid=(l+r)>>1;
      	return min(res,p<=mid?query(ls[id],l,mid,p):query(rs[id],mid+1,r,p));
      }
      il void dfs(int u,int fa){
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		dfs(v,u);
      		rt[u]=merge(rt[u],rt[v],-1e5,1e5);
      	}
      	if(rt[u]){
      //		cout<<u<<"\n";
      		dp[u]=query(rt[u],-1e5,1e5,a[u]);
      	}
      	xd[u].k=b[u],xd[u].b=dp[u];
      	tr[++cnt]=u;
      	insert(rt[u],-1e5,1e5,cnt);
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      	}
      	for(int i=1;i<=n;i++){
      		cin>>b[i];
      	}
      	for(int i=1,u,v;i<n;i++){
      		cin>>u>>v;
      		e[u].pb(v),e[v].pb(u);
      	}
      	dfs(1,0);
      	for(int i=1;i<=n;i++){
      		cout<<dp[i]<<" ";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      G. T-Shirts

      考慮排序后遍歷每件 T 恤衫,對 \(\ge c_i\) 的人進行修改。發(fā)現(xiàn)并不好維護。考慮 FHQ-Treap,將平衡樹分裂為三個部分:\([0,c)\),\([c,2c)\),\([2c,+\infty)\)。顯然第一部分不用動,第二部分修改后會 \(<c\),第三部分修改后仍 \(\ge c\)。于是對第二部分直接暴力修改后插入第一部分,第三部分打上懶標(biāo)記再與第一部分合并即可??紤]時間復(fù)雜度,瓶頸顯然在第二部分上。發(fā)現(xiàn)每次頂多變?yōu)樵瓉淼囊话?,因此每個數(shù)最多暴力修改 \(\log\) 次。于是時間復(fù)雜度 \(O(n\log^2)\)。CF 再次爆炸,因此再次無法貼代碼(

      upd:CF 又好了

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      using namespace std;
      namespace asbt{
      const int maxn=2e5+5;
      int n,m,rt,tot,ls[maxn],rs[maxn];
      int val[maxn],key[maxn],tag[maxn];
      int ans[maxn],tans[maxn];
      struct node{
      	int a,b;
      	il bool operator<(const node &x)const{
      		return b>x.b||b==x.b&&a<x.a;
      	}
      }p[maxn];
      mt19937 rd(time(0));
      il int New(int x){
      	int p=++tot;
      	ls[p]=rs[p]=tag[p]=0;
      	val[p]=x,key[p]=rd();
      	return p;
      }
      il void pushdown(int p){
      	if(tag[p]){
      		tag[ls[p]]+=tag[p];
      		tag[rs[p]]+=tag[p];
      		val[ls[p]]+=tag[p];
      		val[rs[p]]+=tag[p];
      		tag[p]=0;
      	}
      	if(tans[p]){
      		tans[ls[p]]+=tans[p];
      		tans[rs[p]]+=tans[p];
      		ans[ls[p]]+=tans[p];
      		ans[rs[p]]+=tans[p];
      		tans[p]=0;
      	}
      }
      il int merge(int p,int q){
      	if(!p||!q){
      		return p+q;
      	}
      	if(key[p]<key[q]){
      		pushdown(p);
      		rs[p]=merge(rs[p],q);
      		return p;
      	}
      	else{
      		pushdown(q);
      		ls[q]=merge(p,ls[q]);
      		return q;
      	}
      }
      il void split(int id,int &p,int &q,int x){
      	if(!id){
      		p=q=0;
      		return ;
      	}
      	pushdown(id);
      	if(val[id]<x){
      		p=id;
      		split(rs[id],rs[p],q,x);
      	}
      	else{
      		q=id;
      		split(ls[id],p,ls[q],x);
      	}
      }
      il void insert(int &id,int x){
      	int p,q;
      	split(id,p,q,val[x]);
      	id=merge(merge(p,x),q);
      }
      il void dfs(int id,int v,int &x){
      	if(!id){
      		return ;
      	}
      	pushdown(id);
      	dfs(ls[id],v,x),dfs(rs[id],v,x);
      	ls[id]=0,rs[id]=0,val[id]-=v,ans[id]++;
      	insert(x,id);
      }
      il void push(int id){
      	if(!id){
      		return ;
      	}
      	pushdown(id);
      	push(ls[id]),push(rs[id]);
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n;
      	for(int i=1;i<=n;i++){
      		cin>>p[i].a>>p[i].b;
      	}
      	cin>>m;
      	for(int i=1,x;i<=m;i++){
      		cin>>x;
      		insert(rt,New(x));
      	}
      //	puts("666");
      	sort(p+1,p+n+1);
      	for(int i=1;i<=n;i++){
      //		cout<<p[i].a<<" "<<p[i].b<<"\n";
      //		cout<<i<<"\n";
      		int x,y,z;
      //		puts("666");
      		split(rt,x,y,p[i].a);
      //		puts("777");
      		split(y,y,z,p[i].a<<1);
      //		puts("888");
      		tag[z]-=p[i].a,val[z]-=p[i].a;
      		tans[z]++,ans[z]++;
      		dfs(y,p[i].a,x);
      		rt=merge(x,z);
      //	for(int j=1;j<=m;j++){
      //		cout<<ans[j]<<" ";
      //	}
      //	cout<<"\n";
      	}
      //	puts("666");
      	push(rt);
      	for(int i=1;i<=m;i++){
      		cout<<ans[i]<<" ";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      H. New task

      \((a_1,a_2,a_3,a_4,a_5)\) 分為 \(3\) 個部分,即 \((a_1,a_2)\),\(a_3\)\((a_4,a_5)\),分別記為 \(a\),\(b\),\(c\)。因為要求 \(a_2=a_3=a_4\),考慮在 \(a_2\) 維護 \(a\),在 \(a_4\) 維護 \(c\),對每個 \(a\) 值開線段樹,維護一段區(qū)間的 \(a\)、\(b\)、\(c\)、\(ab\)、\(bc\)、\(abc\) 的數(shù)量。樹狀數(shù)組預(yù)處理出 \(a\)\(c\) 即可。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define lwrb lower_bound
      using namespace std;
      namespace asbt{
      const int maxn=1e5+5,mod=1e9+7;
      il int pls(int x,int y){
      	return x+y<mod?x+y:x+y-mod;
      }
      il int sub(int x,int y){
      	return x<y?x-y+mod:x-y;
      }
      int n,m,a[maxn],lsh[maxn],tot,qan[maxn],hou[maxn],rt[maxn];
      struct{
      	int tr[maxn];
      	il int lowbit(int x){
      		return x&-x;
      	}
      	il void build(){
      		memset(tr,0,sizeof(tr));
      	}
      	il void add(int p,int v){
      		for(;p<=n;p+=lowbit(p)){
      			tr[p]+=v;
      		}
      	}
      	il int query(int p){
      		int res=0;
      		for(;p;p-=lowbit(p)){
      			res+=tr[p];
      		}
      		return res;
      	}
      }F;
      struct seg{
      	int a,b,c,ab,bc,abc;
      	seg(int a=0,int b=0,int c=0,int ab=0,int bc=0,int abc=0)
      		:a(a),b(b),c(c),ab(ab),bc(bc),abc(abc){}
      	il seg operator+(const seg &x)const{
      		seg res;
      		res.a=pls(a,x.a),res.b=pls(b,x.b),res.c=pls(c,x.c);
      		res.ab=pls(pls(ab,x.ab),a*1ll*x.b%mod);
      		res.bc=pls(pls(bc,x.bc),b*1ll*x.c%mod);
      		res.abc=pls(pls(abc,x.abc),pls(ab*1ll*x.c%mod,a*1ll*x.bc%mod));
      		return res;
      	}
      };
      struct{
      	int tot,ls[maxn*18],rs[maxn*18];
      	seg tr[maxn*18];
      	il void pushup(int id){
      		tr[id]=tr[ls[id]]+tr[rs[id]];
      	}
      	il void upd(int &id,int l,int r,int p,seg v){
      		if(!id){
      			id=++tot;
      		}
      		if(l==r){
      			tr[id]=v;
      			return ;
      		}
      		int mid=(l+r)>>1;
      		if(p<=mid){
      			upd(ls[id],l,mid,p,v);
      		}
      		else{
      			upd(rs[id],mid+1,r,p,v);
      		}
      		pushup(id);
      	}
      }S;
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n;
      	for(int i=1;i<=n;i++){
      		cin>>a[i];
      		lsh[++tot]=a[i];
      	}
      	sort(lsh+1,lsh+tot+1);
      	tot=unique(lsh+1,lsh+tot+1)-lsh-1;
      	for(int i=1;i<=n;i++){
      		a[i]=lwrb(lsh+1,lsh+tot+1,a[i])-lsh;
      		qan[i]=F.query(a[i]);
      		F.add(a[i],1);
      	}
      	F.build();
      	for(int i=n;i;i--){
      		hou[i]=F.query(a[i]);
      		F.add(a[i],1);
      	}
      	int ans=0;
      	for(int i=1;i<=n;i++){
      		S.upd(rt[a[i]],1,n,i,seg(qan[i],1,hou[i]));
      	}
      	for(int i=1;i<=tot;i++){
      		ans=pls(ans,S.tr[rt[i]].abc);
      	}
      //	cout<<ans<<"\n";
      	cin>>m;
      	while(m--){
      		int opt,x;
      		cin>>opt>>x;
      		ans=sub(ans,S.tr[rt[a[x]]].abc);
      		S.upd(rt[a[x]],1,n,x,opt==1?seg():seg(qan[x],1,hou[x]));
      		ans=pls(ans,S.tr[rt[a[x]]].abc);
      		cout<<ans<<"\n";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      I. Blog Post Rating

      首先可以證明的是,當(dāng)用戶單調(diào)不降,答案一定是最優(yōu)的。證明考慮臨項交換法,設(shè) \(x>y\),那么由下表可知 \((x,y)\) 肯定不比 \((y,x)\) 優(yōu):

      image

      我們還可以發(fā)現(xiàn)的是,隨著 \(a_i\) 從小到大,答案一定是先單調(diào)遞減,再單調(diào)不降。那么我們考慮維護一個按 \(a_i\) 大小排序的線段樹,維護每個位置的 \(a_i\) 與經(jīng)過當(dāng)前位置后的答案之差。我們再用三個 set 維護貢獻為 \(0\)\(1\),\(-1\) 的集合。考慮一個新加入的用戶,對其貢獻分類討論:

      • \(0\),則直接將其加入集合即可,對后面的用戶沒有影響。
      • \(-1\),首先此時它及其之后的差值都會加一,這可能導(dǎo)致最后一個 \(-1\) 變?yōu)?\(0\)。如果最后一個 \(-1\) 不變,那么第一個 \(0\) 將變成 \(1\)。
      • \(1\),它及之后的差值全都減一,那么在它之后可能有一個 \(1\) 變成了 \(0\)。

      用線段樹維護區(qū)間最小值及其最小下標(biāo)即可。時間復(fù)雜度線性對數(shù)。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define pii pair<int,int>
      #define fir first
      #define sec second
      #define mp make_pair
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      const int maxn=5e5+5;
      int n,a[maxn],p[maxn],fp[maxn],tag[maxn<<2];
      pii mn[maxn<<2];
      set<int> _0,_1,__1;
      il void pushup(int id){
      	mn[id]=min(mn[lid],mn[rid]);
      }
      il void pushtag(int id,int v){
      	tag[id]+=v,mn[id].fir+=v;
      }
      il void pushdown(int id){
      	if(tag[id]){
      		pushtag(lid,tag[id]);
      		pushtag(rid,tag[id]);
      		tag[id]=0;
      	}
      }
      il void build(int id,int l,int r){
      	if(l==r){
      		mn[id]=mp(a[p[l]],l);
      		return ;
      	}
      	int mid=(l+r)>>1;
      	build(lid,l,mid);
      	build(rid,mid+1,r);
      	pushup(id);
      }
      il void add(int id,int L,int R,int l,int r,int v){
      	if(L>=l&&R<=r){
      		pushtag(id,v);
      		return ;
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(l<=mid){
      		add(lid,L,mid,l,r,v);
      	}
      	if(r>mid){
      		add(rid,mid+1,R,l,r,v);
      	}
      	pushup(id);
      }
      il pii query(int id,int L,int R,int l,int r){
      	if(L>=l&&R<=r){
      		return mn[id];
      	}
      	pushdown(id);
      	int mid=(L+R)>>1;
      	if(r<=mid){
      		return query(lid,L,mid,l,r);
      	}
      	if(l>mid){
      		return query(rid,mid+1,R,l,r);
      	}
      	return min(query(lid,L,mid,l,r),query(rid,mid+1,R,l,r));
      }
      int main(){
      	ios::sync_with_stdio(0),cin.tie(0);
      	cin>>n;
      	for(int i=1;i<=n;i++){
      		cin>>a[i],p[i]=i;
      	}
      	sort(p+1,p+n+1,[](int x,int y){return a[x]<a[y];});
      	for(int i=1;i<=n;i++){
      		fp[p[i]]=i;
      	}
      	build(1,1,n);
      	for(int i=1;i<=n;i++){
      		pii val=query(1,1,n,fp[i],fp[i]);
      		if(val.fir==0){
      			_0.insert(fp[i]);
      		}
      		else if(val.fir<0){
      			__1.insert(fp[i]);
      			add(1,1,n,fp[i],n,1);
      			int t=*__1.rbegin();
      			if(a[p[t]]==1-(int)__1.size()){
      				__1.erase(t),_0.insert(t);
      				add(1,1,n,t,n,-1);
      			}
      			else if(_0.size()){
      				t=*_0.begin();
      				_0.erase(t),_1.insert(t);
      				add(1,1,n,t,n,-1);
      			}
      		}
      		else{
      			_1.insert(fp[i]);
      			add(1,1,n,fp[i],n,-1);
      			val=query(1,1,n,fp[i],n);
      			if(val.fir<0){
      				_1.erase(val.sec),_0.insert(val.sec);
      				add(1,1,n,val.sec,n,1);
      			}
      		}
      		cout<<(int)_1.size()-(int)__1.size()<<"\n";
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      
      posted @ 2025-07-23 21:03  zhangxy__hp  閱讀(29)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 欧洲码亚洲码的区别入口| 人妻av中文字幕无码专区| 国产av综合色高清自拍| 国产初高中生粉嫩无套第一次| 扎囊县| 日韩少妇人妻vs中文字幕| 极品白嫩少妇无套内谢| 国产精品午夜福利免费看| 三人成全免费观看电视剧高清| 国产亚洲真人做受在线观看| 午夜精品福利亚洲国产| 亚洲欧美日韩愉拍自拍美利坚| 少妇裸交aa大片| 久久精品无码鲁网中文电影| 一本色道久久东京热| 亚洲av天堂天天天堂色| 精品无码国产污污污免费| 九九在线精品国产| 久热久精久品这里在线观看| 97se亚洲国产综合自在线观看| 视频一区二区三区在线视频| 影音先锋啪啪av资源网站| 亚洲V天堂V手机在线| 国产精品视频一区二区三区无码| 亚洲第一福利网站在线观看| 一亚洲一区二区中文字幕| 国产线播放免费人成视频播放| 麻豆亚洲精品一区二区| 亚洲乱码国产乱码精品精| 噜噜噜噜私人影院| 久久久久国产精品人妻| 国产亚洲精品日韩av在| 69精品丰满人妻无码视频a片| 久久精品国产再热青青青| 国产在线一区二区不卡| 精品久久人人妻人人做精品| 日本一道一区二区视频| 成人免费A级毛片无码片2022| 激情国产一区二区三区四区| 国产一区二区三区精品综合| 精品无码老熟妇magnet|