• 【洛谷P5113】—魔女的夜宴Sabbat of the witch(分块+基数排序)


    传送门

    绫地宁宁天下第一!


    考虑对于每一个块,用一个setset来维护每次整块的覆盖
    对于每个点再维护一个setset表示对散块的覆盖
    将块内每个点按照最后一次覆盖的时间排序
    维护一下后缀和
    对于询问,散块暴力加
    整块二分找到第一个在整块覆盖后被修改的点
    前面所有答案就都是整块的答案,加上后缀和即可
    每次覆盖整块加进去,散块重构
    每次撤销直接删去那次覆盖,散块重构

    这样可以做到O(nnlogn)O(nsqrt nlogn)

    考虑实际上每次加入的时间都是单调的
    所以维护一个栈就可以了
    对于每次重构,可以利用基数排序
    由于保证赋值不超过6500065000
    可以用bas=256bas=256基排
    二分可以每次重构的时候维护一个指针指向第一个小于整块覆盖的点
    由于有撤销
    每次重构的时候维护一下当前时间
    每次询问的时候将当前时间和上次重构比较
    如果在重构之前就暴力跳指针就可以了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=100005,S=251,M=255;
    char x;
    int del[N],n,m,tot;
    namespace Stk{
    	int cnt,adj[N],nxt[N*(S+14)],to[N*(S+14)];
    	inline void push(int u,int v){
    		nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
    	}
    	inline int front(int x){
    		return to[adj[x]];
    	}
    	inline void pop(int x){
    		while(del[to[adj[x]]])adj[x]=nxt[adj[x]];
    	}
    }
    using Stk::pop;
    using Stk::front;
    using Stk::push;
    int bel[N],L[N],R[N],pos[N];
    struct opt{
    	int l,r,v;
    }q[N];
    struct block{
    	static cs int S=::S+10;
    	int pos,siz,pt,last;
    	int val[S],a[S],stk[N],top;
    	ll sum[S],s;
    	inline ll Sort(){
    		static int buc[S],rk[S];
    		ll res=0;
    		for(int i=1;i<=siz;i++)val[i]=front(i+pos),res+=(val[i]?0:a[i]);
    		for(int i=0;i<=M;i++)buc[i]=0;
    		for(int i=1;i<=siz;i++)buc[val[i]&M]++;
    		for(int i=1;i<=M;i++)buc[i]+=buc[i-1];
    		for(int i=siz;i;i--)rk[buc[val[i]&M]--]=val[i];
    		for(int i=0;i<=M;i++)buc[i]=0;
    		for(int i=1;i<=siz;i++)buc[val[i]>>8]++;
    		for(int i=1;i<=M;i++)buc[i]+=buc[i-1];
    		for(int i=siz;i;i--)val[buc[rk[i]>>8]--]=rk[i];
    		return res;
    	}
    	inline void build(){
    		s=0;
    		for(int i=1;i<=siz;i++)s+=a[i];
    		sum[0]=s;
    	}
    	inline void rebuild(){
    		ll res=Sort();last=stk[top];
    		for(int i=siz-1;~i;i--)sum[i]=sum[i+1]+q[val[i+1]].v;sum[0]+=res;
    		pt=0;
    		while(pt<siz&&val[pt+1]<last)pt++;
    		s=sum[pt]+1ll*pt*q[last].v;
    	}
    	inline void insert(int x){
    		stk[++top]=x,s=1ll*q[x].v*siz;
    	}
    	inline void reset(){
    		while(del[stk[top]])top--;
    		if(stk[top]<=last){
    			while(pt&&val[pt]>=stk[top])pt--;
    			s=sum[pt]+1ll*pt*q[stk[top]].v;
    		}
    		else s=1ll*q[stk[top]].v*siz;
    	}
    	inline ll query(int l,int r){
    		ll res=0;
    		int t=stk[top];
    		if(t)for(int i=l;i<=r;i++)res+=(front(i)<t)?q[t].v:q[front(i)].v;
    		else for(int i=l;i<=r;i++)res+=(front(i)?q[front(i)].v:a[i-pos]);
    		return res;
    	}
    }A[N/S+5];
    char y;
    inline void update(int l,int r,int v){
    	if(bel[l]==bel[r]){
    		for(int i=l;i<=r;i++)push(i,v);
    		A[bel[l]].rebuild();return;
    	}
    	for(int i=l;i<=R[bel[l]];i++)push(i,v);
    	A[bel[l]].rebuild();
    	for(int i=L[bel[r]];i<=r;i++)push(i,v);
    	A[bel[r]].rebuild();
    	for(int i=bel[l]+1;i<bel[r];i++)A[i].insert(v);
    }
    inline void delet(int l,int r){
    	if(bel[l]==bel[r]){
    		for(int i=l;i<=r;i++)pop(i);
    		A[bel[l]].rebuild();return;
    	}
    	for(int i=l;i<=R[bel[l]];i++)pop(i);
    	A[bel[l]].rebuild();
    	for(int i=L[bel[r]];i<=r;i++)pop(i);
    	A[bel[r]].rebuild();
    	for(int i=bel[l]+1;i<bel[r];i++)A[i].reset();
    }
    inline ll query(int l,int r){
    	if(bel[l]==bel[r])return A[bel[l]].query(l,r);
    	ll res=0;
    	res+=A[bel[l]].query(l,R[bel[l]]);
    	res+=A[bel[r]].query(L[bel[r]],r);
    	for(int i=bel[l]+1;i<bel[r];i++)res+=A[i].s;
    	return res;
    }
    ll last;
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)bel[i]=(i-1)/S+1;
    	for(int i=1;i<=n;i++)A[bel[i]].a[(i-1)%S+1]=read();
    	for(int i=1;i<=bel[n];i++)L[i]=(i-1)*S+1,R[i]=i*S;
    	R[bel[n]]=n;
    	for(int i=1;i<=bel[n];i++)A[i].pos=L[i]-1;
    	for(int i=1;i<=n;i++)A[bel[i]].siz=i-L[bel[i]]+1;
    	for(int i=1;i<=bel[n];i++)A[i].build();
    	while(m--){
    		int op=read();
    		if(op==1){
    			int l=read()^last,r=read()^last,v=read();
    			q[++tot]=opt{l,r,v};
    			update(l,r,tot);
    		}
    		else if(op==2){
    			int l=read()^last,r=read()^last;
    			cout<<(last=query(l,r))<<'
    ';
    		}
    		else{
    			int x=read()^last;
    			del[x]=1;
    			delet(q[x].l,q[x].r);
    		}
    	}
    }
    
  • 相关阅读:
    [HNOI 2017]影魔
    [HNOI 2016]树
    [HNOI 2011]卡农
    [SCOI 2016]美味
    [SDOI 2011]染色
    [HNOI 2016]最小公倍数
    eclipse实现热部署和热加载
    mysql中时间比较的实现
    如何把本地项目部署到服务器上
    Linux部署项目和常用命令
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328401.html
Copyright © 2020-2023  润新知