bzoj 3460: Jc的宿舍 莫队算法

       一开始感觉是分块,但是好像不太兹瓷。于是觉得是莫队。

      但是他有强制在线,,而且莫队还是N^1.5logN的,感觉很不兹瓷。

      后来发现是假的在线。。。并且找到了一个题解发现就是N^1.5logN的,然后就做完了。

      yy了一个做法就是每16个分成一块,然后O(16)修改,O(N/16)询问,配合莫队就是O(16N^1.5+N^2/16),不知道能不能过(当然不是16应该也是兹瓷的)。

AC代码如下:

#include
#define ll long long
#define N 200005
using namespace std;

int n,m,rt,pt,key,blk,dfsclk,cnt,fst[N],nxt[N],a[N],q[N],rk[N];
int d[N],fa[N],son[N],sz[N],anc[N],lf[N],rg[N],id[N];
ll res,c[N],ans[N]; bool vis[N];
struct node{ int x,y,k; }b[N];
int read(){
	int x=0; char ch=getchar();
	while (ch<'0' || ch>'9') ch=getchar();
	while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
	return x;
}
int lca(int x,int y){
	for (; anc[x]!=anc[y]; x=fa[anc[x]])
		if (d[anc[x]]lf[y]) swap(x,y);
	cnt++; b[cnt]=(node){(lca(x,y)==x)?lf[x]:rg[x],lf[y],cnt+1};
}
void add(int x,ll y){
	for (; x<=n; x+=x&-x) c[x]+=y;
}
ll getsum(int x){
	ll y=0; for (; x; x^=x&-x) y+=c[x]; return y;
}
void mdy(int y){
	int x=rk[y]; vis[y]^=1;
	if (vis[y]){
		pt++; add(x,(ll)a[y]*n+1);
		ll z=getsum(x)-1; res+=(ll)a[y]*(pt-z%n-1)+z/n;
	} else{
		ll z=getsum(x)-1; res-=a[y]*(pt-z%n-1)+z/n;
		pt--; add(x,-((ll)a[y]*n+1));
	}
}
void dfs(int x){
	int y; sz[x]=1;
	for (y=fst[x]; y; y=nxt[y]){
		d[y]=d[x]+1;
		dfs(y); sz[x]+=sz[y];
		if (sz[y]>sz[son[x]]) son[x]=y;
	}
}
void dvd(int x,int tp){
	int y; anc[x]=tp;
	lf[x]=++dfsclk; id[dfsclk]=x;
	if (son[x]) dvd(son[x],tp);
	for (y=fst[x]; y; y=nxt[y])
		if (y!=son[x]) dvd(y,y);
	rg[x]=++dfsclk; id[dfsclk]=x;
}
bool cmp1(int x,int y){ return a[x]r) mdy(id[++r]);
		while (b[i].x>l) mdy(id[l++]); while (b[i].y>1); i++){
		tmp=ans[i<<1|(tmp&1)];
		printf("%lld\n",tmp);
	}
	return 0;
}


by lych

2017.2.19

你可能感兴趣的:(bzoj)