zoukankan      html  css  js  c++  java
  • 【纪中集训2019.3.15】恶熊咆哮

    题目

    描述

    (n)只熊,初始时坐标为((x_i,y_i))

    这些熊会按照标号依次吼叫,当第(i)只熊吼叫,其他熊会移动;

    ((x_i,y_i))会移动到((x_i pm 1,y_i pm 1))离吼叫的熊欧几里得距离最小的位置;

    问当第(i)只熊生病了,不吼叫也不移动,其他的熊依次吼叫后的(sum_{i=1}^{n}x_iy_i);

    依次输出(ans_i);

    范围

    (2 le n le 2.5 imes 10^5 , 1 le x_i ,y_i le 10^6)

    题解

    • $Part 1 $

    • 横纵坐标独立,所以分别考虑每一维的情况;

    • 设将熊按照坐标大小排序并差分,设(d_i = x_i - x_{i-1},pos_i)为熊离散后的下标;

    • 那么操作可以看成找到(pos_i)之前的第一个不为(0)的数字(--),找到(pos_i)及之后第一个不为(0)的数字(--);

    • 我们可以找到大家都好好的时候这样子的吼叫区间((L_i,R_i));

    • 容易发现他们是互相包含或者端点相接;

    • 当第(i)熊不吼叫时,它减少的贡献初始也是((L_i,R_i)),但是 $ i+1 o m $ 的熊的吼叫区间会影响$ (L_i,R_i) $ ;

    • 可以发现最终(L_i,R_i)也是一个区间,只要统计了所有最终这样的区间就可以统计答案;

    • $Part 2 $

    • 考虑第(j)只熊吼叫时,​((L_j,R_j)(j>i))依次对​((L_i,R_i))的影响;

      • 当且仅当 $ L_j le L_i , R_i le R_j $ 时 $ i $ 会被 $ j $ 影响;
      • 1.若(R_i<pos_j),则新的区间为((L_j,L_i));
      • 2.若(L_i >= pos_j),则新的区间为((R_i,R_j));
      • 3.若(L_i<pos_j且pos_j<=R_i) , 则新的区间为((L_j,R_j));
    • 考虑如何维护这些区间的变化;

    • 由于一次变化后,所有被影响到的区间一定是在左端点或者右端点;

    • 在每个区间的左端点记录(Right)集合,对右端点记录(Left)集合;

    • 对于在(pos_i)左边的区间的(Left),显然可以直接加到(j)(Right)上;

    • 右边区间的(Right)同理;

    • 对于左边区间的(Right),可以发现在变化过后所有的区间变成了相同的区间,并查集合并即可

    • 右边区间的(Left)和跨越(pos_i)的的区间同理;

    • 上述过程可以简单链表+并查集实现,查找包含的区间可以用(set)维护;

    • $Part 3 $

    • 考虑如何求最终的答案;

    • 先预处理一个正常情况下的答案;

    • 对于每个熊,设正常情况下最终位置为:((x_i,y_i)),相当于变成了((x_i pm 1, y_i pm 1));

    • ((x_i+a)(y_i+b) - x_iy_i = ax_i + by_i + ab);

    • 前缀和维护(ax_i)(by_i)再加个二维数点维护(ab)即可;

    • 。。。。。。

      #include<bits/stdc++.h>
      #define ll long long 
      #define mk make_pair
      #define fir first
      #define sec second 
      using namespace std;
      const int N=1000010;
      int n,px[N],py[N],idx[N],idy[N],dx[N],dy[N],p[N],rk[N];
      int fa[N],pre[N],nxt[N],nt[N],sz,sta[N],top;
      int Lx[N],Rx[N],Ly[N],Ry[N],Lx0[N],Rx0[N],Ly0[N],Ry0[N],tx[N],ty[N],rkx[N],rky[N];
      ll sumx[N],sumy[N],pre_ans;
      inline char gc(){
      	static char*p1,*p2,s[1000000];
      	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      	return(p1==p2)?EOF:*p1++;
      }
      inline int rd(){
      	int x=0;char c=gc();
      	while(c<'0'||c>'9')c=gc();
      	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
      	return x;
      }
      inline bool cmpx(const int&a,const int&b){return px[a]<px[b];}
      inline bool cmpy(const int&a,const int&b){return py[a]<py[b];}
      int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
      int find_nxt(int x){return nxt[x]==x?x:nxt[x]=find_nxt(nxt[x]);}
      int find_pre(int x){return pre[x]==x?x:pre[x]=find_pre(pre[x]);}
      struct table{int hd,tl;};
      void link(table&A,int x){
      	if(!A.hd){nt[A.hd=A.tl=x]=0;return;}
      	nt[A.tl]=x;nt[A.tl=x]=0;
      }
      void link(table&A,table B){
      	if(!B.hd)return;
      	if(!A.hd){A=B;return;}
      	nt[A.tl]=B.hd;A.tl=B.tl;
      }
      struct inter{
      	int l,r;
      	table L,R;
      	void init(const int&id,const int&tl,const int&tr){
      		L.hd=R.hd=L.tl=R.tl=0; 
      		l=tl,r=p[id]=tr;
      //		link(L,id);
      	}
      }A[N];
      typedef pair<int,int>pii;
      set<pii>S; set<pii>::iterator st,ed,I;
      void solve(const int*id,int*d,int*L,int*R,int*L0,int*R0){
      	d[0]=d[n]=n+1;
      	for(int i=0;i<=n;++i)pre[i]=nxt[i]=fa[i]=i;
      	for(int i=1;i<n;++i)if(!d[i])pre[i]=i-1,nxt[i]=i+1;
      	for(int i=1;i<=n;++i){
      		int pos=id[i]-1,l=find_pre(pos),r=find_nxt(pos+1),f;
      		L0[i]=l;R0[i]=r;
      		d[l]--;if(!d[l])pre[l]=l-1,nxt[l]=l+1;
      		d[r]--;if(!d[r])pre[r]=r-1,nxt[r]=r+1;
      		A[i].init(i,l,r);
      		st=S.lower_bound(mk(l,0));
      		ed=S.lower_bound(mk(r,0));
      		inter&tmp=A[i];
      		for(I=st;I!=ed;++I){
      			inter now=A[(*I).sec];
      			if(now.r<=pos){
      				if(now.L.hd){
      					p[f=now.L.hd]=now.l;
      					for(int j=nt[f];j;j=nt[j])fa[find(j)]=find(f);
      					link(tmp.L,f);
      				}
      				link(tmp.L,now.R); 
      			}else if(now.l>pos){
      				link(tmp.R,now.L);
      				if(now.R.hd){
      					p[f=now.R.hd]=now.r;
      					for(int j=nt[f];j;j=nt[j])fa[find(j)]=find(f);
      					link(tmp.R,f);
      				}
      			}else{
      				int j=now.L.hd;
      				if(j&&p[j]<=pos){
      					p[f=j]=now.l;
      					for(j=nt[f];j&&p[j]<=pos;j=nt[j])fa[find(j)]=find(f);
      					link(tmp.L,f);
      				}
      				for(;j;j=nt[j])fa[find(j)]=find(i);
      				for(j=now.R.hd;j&&p[j]<=pos;j=nt[j])fa[find(j)]=find(i);
      				if(j){
      					p[f=j]=now.r;
      					for(j=nt[f];j;j=nt[j])fa[find(j)]=find(f);
      					link(tmp.R,f);
      				}
      			}
      		}
      		link(tmp.L,i);
      		S.erase(st,ed);
      		S.insert(mk(l,i));
      	}
      	st=S.begin();ed=S.end();
      	for(I=st;I!=ed;++I){
      		inter tmp=A[(*I).sec];
      		for(int j=tmp.L.hd;j;j=nt[j])L[j]=tmp.l,R[j]=p[j];
      		for(int j=tmp.R.hd;j;j=nt[j])R[j]=tmp.r,L[j]=p[j];
      	}
      	S.erase(st,ed);
      	for(int i=1;i<=n;++i)if(find(i)!=i)L[i]=L[fa[i]],R[i]=R[fa[i]];
      }
      struct tree{
      	int sz,rt[N],ls[N*20],rs[N*20],sum[N*20];
      	void insert(int&k,int lst,int l,int r,int x){
      		sum[k=++sz]=sum[lst]+1;
      		ls[k]=ls[lst],rs[k]=rs[lst];
      		if(l==r)return;
      		int mid=l+r>>1;
      		if(x<=mid)insert(ls[k],ls[lst],l,mid,x);
      		else insert(rs[k],rs[lst],mid+1,r,x);
      	}
      	int que(int k,int lst,int l,int r,int x,int y){
      		if(l==x&&r==y)return sum[k]-sum[lst];
      		int mid=l+r>>1;
      		if(y<=mid)return que(ls[k],ls[lst],l,mid,x,y);
      		else if(x>mid)return que(rs[k],rs[lst],mid+1,r,x,y);
      		else return que(ls[k],ls[lst],l,mid,x,mid)+que(rs[k],rs[lst],mid+1,r,mid+1,y);
      	}
      	void insert(int x,int y){insert(rt[x],rt[x-1],1,n,y);}
      	int query(int lx,int rx,int ly,int ry){
      		if(lx>rx||ly>ry)return 0;
      		return que(rt[rx],rt[lx-1],1,n,ly,ry);
      	}
      }T;
      void pre_cal(){
      	for(int i=0;i<=n;++i)dx[i]=dy[i]=0;
      	for(int i=1;i<=n;++i)dx[Rx0[i]+1]--,dy[Lx0[i]]++;
      	for(int i=1;i<=n;++i)dx[i]+=dx[i-1],dy[n-i+1]+=dy[n-i+2];
      	for(int i=1;i<=n;++i)px[idx[i]]+=dx[i]+dy[i];
      	for(int i=0;i<=n;++i)dx[i]=dy[i]=0;
      	for(int i=1;i<=n;++i)dx[Ry0[i]+1]--,dy[Ly0[i]]++;
      	for(int i=1;i<=n;++i)dx[i]+=dx[i-1],dy[n-i+1]+=dy[n-i+2];
      	for(int i=1;i<=n;++i)py[idy[i]]+=dx[i]+dy[i];
      	for(int i=1;i<=n;++i)pre_ans+=1ll*px[i]*py[i];
      	for(int i=1;i<=n;++i)sumx[i]=px[idy[i]]+sumx[i-1],sumy[i]=py[idx[i]]+sumy[i-1];
      }
      ll cal(int id,int lx,int rx,int ly,int ry){
      	ll tmp=pre_ans;
      	tmp-=sumy[lx];
      	tmp+=sumy[n]-sumy[rx];
      	tmp-=sumx[ly];
      	tmp+=sumx[n]-sumx[ry];
      	tmp+=T.query(1,lx,1,ly);
      	tmp-=T.query(1,lx,ry+1,n);
      	tmp-=T.query(rx+1,n,1,ly);
      	tmp+=T.query(rx+1,n,ry+1,n);
      	int fgx=rkx[id]<=lx?-1:rkx[id]>rx?1:0;
      	int fgy=rky[id]<=ly?-1:rky[id]>ry?1:0;
      	tmp-=(ll)(px[id]+fgx)*(py[id]+fgy);
      	tmp+=(ll)tx[id]*ty[id];
      	return tmp;
      }
      int main(){
      	freopen("bear.in","r",stdin);
      	freopen("bear.out","w",stdout);
      	n=rd();
      	for(int i=1;i<=n;++i){
      		tx[i]=px[i]=rd();
      		ty[i]=py[i]=rd();
      		idx[i]=idy[i]=fa[i]=i;
      	}
      	sort(idx+1,idx+n+1,cmpx);
      	sort(idy+1,idy+n+1,cmpy);
      	for(int i=1;i<=n;++i){
      		rkx[idx[i]]=i;
      		rky[idy[i]]=i;
      		dx[i-1]=px[idx[i]]-px[idx[i-1]];
      		dy[i-1]=py[idy[i]]-py[idy[i-1]]; 
      	}
      	for(int i=1;i<=n;++i)T.insert(i,rky[idx[i]]);
      	memset(Lx,-1,sizeof(Lx));
      	memset(Rx,-1,sizeof(Rx));
      	memset(Ly,-1,sizeof(Ly));
      	memset(Ry,-1,sizeof(Ry));
      	solve(rkx,dx,Lx,Rx,Lx0,Rx0);
      	solve(rky,dy,Ly,Ry,Ly0,Ry0);
      	pre_cal();
      	for(int i=1;i<=n;++i){
      		ll ans = cal(i,Lx[i],Rx[i],Ly[i],Ry[i]);
      		printf("%lld
      ",ans);
      	}
      	return 0;
      }
      
  • 相关阅读:
    XML-SAX
    aio-epoll
    aio-java
    设计模式-策略模式、命令模式
    java-io一
    计算机网络-tcp的可靠性
    计算机网络-tcp简介
    设计模式-单例模式、工厂模式
    Cookie和Session简述
    mysql-优化二
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10617178.html
Copyright © 2011-2022 走看看