在考试前要看!

首先是平衡树,然后是整除分块

//最终版本 
#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long ll;
using namespace std;
ll n,m;

struct Splay{
	#define N (ll)12e6
	ll siz[N],fa[N],son[N][3],vul[N],tot,root,cnt[N];
	void UP(ll x){
		siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
	}
	bool dir(ll x){
		return son[fa[x]][1]==x;
	}
	void rotate(ll x){
		ll y=fa[x],z=fa[y],k=dir(x),w=son[x][k^1];
		fa[x]=z,son[z][dir(y)]=x;
		fa[y]=x,son[x][k^1]=y;
		fa[w]=y,son[y][k]=w;
		UP(y),UP(x);
	}
	void splay(ll x,ll goal=0){
		while(fa[x]!=goal){
			ll y=fa[x],z=fa[y];
			if(z!=goal){
				if(dir(x)==dir(y))rotate(y);
				else rotate(x); 
			}
			rotate(x);
		}
		if(goal==0)root=x;
	}
	void find(ll x){
		if(!root)return ;
		ll cur=root;
		while(son[cur][x>vul[cur]]&&x!=vul[cur])
			cur=son[cur][x>vul[cur]];
		splay(cur);
	}
	ll LR(ll x,ll k){
		find(x);
		if(k==0&&vul[root]<x)return root;
		if(k==1&&vul[root]>x)return root;
		ll cur=son[root][k];
		while(son[cur][k^1])cur=son[cur][k^1];
		return cur;
	}
	void insert(ll x){
		ll cur=root,p=0;
		while(cur&&x!=vul[cur]){
			p=cur;
			cur=son[cur][x>vul[cur]];
		}
		if(cur)cnt[cur]++;
		else {
			cur=++tot;
			if(p)son[p][x>vul[p]]=cur;
			siz[cur]=cnt[cur]=1;
			son[cur][0]=son[cur][1]=0;
			fa[cur]=p,vul[cur]=x;
		}
		splay(cur);
	}
	void Delete(ll x){
		ll le=LR(x,0),re=LR(x,1);
		splay(le),splay(re,le);
		ll del=son[re][0];
		if(cnt[del]>1)cnt[del]--,splay(del);//注意是大于1 
		//splay(del)更新路上所有点的信息 
		else son[re][0]=0;
		UP(re),UP(le);
	}
	ll Kth(ll k){
		ll cur=root;
		while(1){
			if(k<=siz[son[cur][0]]&&son[cur][0])
				cur=son[cur][0];
			else if(k>siz[son[cur][0]]+cnt[cur]){
				k-=siz[son[cur][0]]+cnt[cur];
				cur=son[cur][1];
			}
			else return cur;
		}
	}
	ll get_rank(ll x){
		find(x);
		if(vul[root]<x)return siz[son[root][0]]+cnt[root];
		else return siz[son[root][0]];
	}
}T;

int main(){
	cin>>n;
	T.insert(1e8);
	T.insert(-1e8);
	for(ll i=1;i<=n;i++){
		ll a1,a2;
		scanf("%lld%lld",&a1,&a2);
		switch(a1){
			case 1:T.insert(a2);break;
			case 2:T.Delete(a2);break;
			case 3:printf("%lld\n",T.get_rank(a2));break;
			case 4:printf("%lld\n",T.vul[T.Kth(a2+1)]);break;
			case 5:printf("%lld\n",T.vul[T.LR(a2,0)]);break;
			case 6:printf("%lld\n",T.vul[T.LR(a2,1)]);break;
		}
	}
}
for(ll i=1;i<=n;i++){
  ll r;
  for(ll l=1;l<=m;l=r){
    r=max(l+1,a[i]/(a[i]/l)+1);
    vec[i].push_back(a[i]/l);
  }
}

在半分钟内写完减少能量消耗的树状数组

struct ST{
	ll f[N];
	ll lowbits(ll x){return x&-x;}
	ll inquire(ll x,ll tmp=0){
		for(;x;x-=lowbits(x))(tmp+=f[x])%=mod;
		return tmp;
	}
	ll query(ll l,ll r){
		if(r<l)return 0;
		return (inquire(r)-inquire(l-1)+mod)%mod;
	}
	void modify(ll x,ll del){
		for(;x<=n;x+=lowbits(x))(f[x]+=del)%=mod;
	}
}T;

敲响警钟:矩阵乘法需要累乘的时候要把答案矩阵写在左边,此时答案矩阵是一个横矩阵(大概吧)
逆元递推

\[inv[i]=(mod-mod/i)*inv[mod\%i]\%mod (其中M为模数,要求为奇质数) \]

\[inv[1]=1; \]

posted @ 2022-10-28 18:48  蒟蒻丁  阅读(24)  评论(1编辑  收藏  举报