WC2022回滚莫队求调
查看原帖
WC2022回滚莫队求调
565923
Cyh29hao楼主2023/1/16 00:37
#include <bits/stdc++.h>
#define ll long long
#define T 0
using namespace std;
const int mx=5e5+5;
int n,m,col,a[mx],bel[mx],rnk[mx];
ll ans[mx],all,ANS[2];

struct query{
	int l,r,id;
	inline bool operator < (const query &x)const{
		return bel[l]!=bel[x.l]?bel[l]<bel[x.l]:r>x.r;
	}
}q[mx];
struct node{
	int val,id;
	inline bool operator < (const node &x)const{
		return x.val<val;
	}
}b[mx];
struct list{
	int l,r;
}link[mx],orig[mx],last[mx];
inline void del(int i,int id){
	if(T)printf("        del(%d)\n",i);
	if(link[i].l)ANS[id]+=abs(link[i].l-i);
	if(link[i].r)ANS[id]+=abs(link[i].r-i);
	if(link[i].l && link[i].r)ANS[id]-=abs(link[i].l-link[i].r);
	if(link[i].l)link[link[i].l].r=link[i].r;
	if(link[i].r)link[link[i].r].l=link[i].l;
}
inline void add(int i,int j){
	link[i].r=j;link[j].l=i;
	all+=abs(i-j);
}
inline int read(){
	int x=0;char ch=getchar();
	while(ch<48||ch>57)ch=getchar();
	while(48<=ch && ch<=57)x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
inline void write(ll x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10|48);
}
inline void init(){
	n=read();m=read();
	col=sqrt(n);for(int i=1;i<=n;++i)bel[i]=(i-1)/col+1;
	for(int i=1;i<=n;++i)b[i].val=a[i]=read(),b[i].id=i;
	for(int i=1;i<=m;++i)q[i].l=read(),q[i].r=read(),q[i].id=i;
	sort(q+1,q+1+m);sort(b+1,b+1+n);//O(mlogm+nlogn)
	for(int i=1;i<=n;++i)rnk[b[i].val]=b[i].id;
	for(int i=2;i<=n;++i)add(rnk[i-1],rnk[i]);//O(n)
	if(T){
		printf("  rnk:");for(int i=1;i<=n;++i)printf("%d ",rnk[i]);printf("\n\n");
		printf("  all=%lld\n",all);
	}
}
#define start(x) (x-1)*col+1
#define end(x) x*col
inline void solve(){
	for(int i=1,l=0,r=0,now=0;i<=m;++i){
		int ql=q[i].l,qr=q[i].r,id=q[i].id;
		if(bel[ql]>now){//get to a new column
			if(now){
				memcpy(link,last,sizeof link);//back to last links
				l=start(now);ANS[0]=0;
				while(l<start(bel[ql]))del(l++,0);
				all-=ANS[0];//delete old column
			}
			memcpy(last,link,sizeof link);//save original links
			now=bel[ql];//update column
			r=n;ANS[1]=0;//r.reset
		}//sumO=O(sqrt(n)^2)=O(n)
		l=start(now);ANS[0]=0;//l reset
		
		if(T){
			printf("    id=%d,ql=%d,qr=%d,l=%d,r=%d,all=%lld\n",id,ql,qr,l,r,all);
		}
		
		while(r>qr)del(a[a[r--]],1);//r's contribute continues; sumO=O(nsqrt(n))
		memcpy(orig,link,sizeof link);
		while(l<ql)del(a[a[l++]],0);//l only have a try;sumO=O(msqrt(n))
		memcpy(link,orig,sizeof orig);
		
		if(T){
			printf("      ans0=%lld,ans1=%lld\n",ANS[0],ANS[1]);
		}
		
		ans[id]=all-ANS[0]-ANS[1];//ans=all-deleted
	}//sumO=(n+m)sqrt(n)+(n+m)*memcpy
}


int main()
{
	//freopen("P5906_4.in","r",stdin);freopen("test.in","w",stdout);
	init();
	solve();
	for(int i=1;i<=m;++i)write(ans[i]),puts("");
	return 0;
}

rt

回滚莫队90%数据TLE,delete操作也是O(1)的,是否是memcpy函数效率影响?如果要替换掉memcpy应该怎么存之前的链表?

或者哪位大佬能告诉我哪里有这题的大样例吗qwq

2023/1/16 00:37
加载中...