BJOI2017 开车

  • 一道神题,对拍狂该了两个小时,终于过了,常数还巨大
  • 首先答案最优肯定是车和加油站都排好须一一对应,现在我们将所有的有用坐标离散化,考虑维护每一段距离对答案的贡献
  • 我们发现,如果把车设成1,加油站设成-1,放在其所在的位置上,累一遍前缀和,那么每个位置上的数值就是现在失配的车或加油站,那么贡献为其绝对值乘上那段区间的距离。
  • 我们考虑分块维护贡献,对每个块对其按前缀和排序,这样可以将绝对值去掉,改动车的位置实际上就是把原来地方减一,将新的地方加一
  • 对于边角我们暴力修改并重构该块,重新计算贡献,对于完整的块我们打上lazy标记,计算式二分零点位置计算贡献即可
#include<bits/stdc++.h>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=5e4+5;
template<typename T>bool cmax(T &a,T b){return (a<b)?a=b,1:0;}
template<typename T>bool cmin(T &a,T b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
  T ans=0,f=1;
  char ch=getchar();
  while(!isdigit(ch)&&ch!='-')ch=getchar();
  if(ch=='-')f=-1,ch=getchar();
  while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
  return ans*f;
}
template<typename T>void write(T x,char y)
{
  if(x==0)
  {
      putchar('0');putchar(y);
      return;
  }
  if(x<0)
  {
      putchar('-');
      x=-x;
  }
  static char wr[20];
  int top=0;
  for(;x;x/=10)wr[++top]=x%10+'0';
  while(top)putchar(wr[top--]);
  putchar(y);
}
void file()
{
  #ifndef ONLINE_JUDGE
      freopen("4908.in","r",stdin);
      freopen("4908.out","w",stdout);
  #endif
}
int n,m;
int a[N],b[N],q[N*3],tot;
int car[N],pos[N];
void input()
{
	n=read<int>();
	For(i,1,n)a[i]=q[++tot]=read<int>();
	For(i,1,n)b[i]=q[++tot]=read<int>();
	m=read<int>();
	For(i,1,m)car[i]=read<int>(),pos[i]=q[++tot]=read<int>();
}
#define find(x) lower_bound(q+1,q+tot+1,x)-q
int ac_pos[N*3];
ll sum[N*3],dis[N*3];
int block,st[400],ed[400],lazy[400],tim,blcok;
ll val[400],num[400][400];
ll ans;
struct node
{
	ll sum,dis,id;
	bool operator < (const node &s)const
	{return sum<s.sum;}
}e[N*3];
ll w[400][400];
void rebuild(int id)
{
//	cout<<"build"<<' '<<id<<endl;
//	For(i,st[id],ed[id])cout<<e[i].sum<<' '<<e[i].dis<<endl;
//	puts("");
	ans-=val[id];val[id]=0;
	For(i,st[id],ed[id])e[i].sum+=lazy[id];
	lazy[id]=0;
	sort(e+st[id],e+ed[id]+1);
	For(i,st[id],ed[id])
	{
		ac_pos[e[i].id]=i;
		num[id][i-st[id]+1]=num[id][i-st[id]]+e[i].dis*e[i].sum;
		w[id][i-st[id]+1]=w[id][i-st[id]]+e[i].dis;
		//	cout<<e[i].sum<<' '<<e[i].dis<<endl;
		val[id]+=abs(e[i].sum)*e[i].dis;	
	}
	ans+=val[id];
	//puts("");
}
void recal(int id)
{
	//if(!lazy[id])return;
	//cout<<"id"<<' '<<id<<endl;
	//cout<<"val"<<' '<<val[id]<<endl;
	//cout<<"lazy"<<' '<<lazy[id]<<endl;
	//For(i,st[id],ed[id])cout<<e[i].sum<<' '<<e[i].dis<<endl;
	ans-=val[id];val[id]=0;
	node temp={-lazy[id],0};
	int p;
	p=lower_bound(e+st[id],e+ed[id]+1,temp)-e-st[id];
	//cout<<"p"<<' '<<p<<endl;
	//cout<<"num"<<' '<<num[id][p]<<endl;
	val[id]+=abs((num[id][p])+w[id][p]*lazy[id]);
	temp={-lazy[id]+1,0};
	p=lower_bound(e+st[id],e+ed[id]+1,temp)-e-st[id];
	//cout<<"p"<<' '<<p<<endl;
	val[id]+=abs((num[id][ed[id]-st[id]+1]-num[id][p])+lazy[id]*(w[id][ed[id]-st[id]+1]-w[id][p]));
	ans+=val[id];
	//cout<<"val"<<' '<<val[id]<<endl;
	//puts("");
}
int bl[N*3];
void init()
{
	sort(q+1,q+tot+1);
	tot=unique(q+1,q+tot+1)-q-1;
	For(i,1,n)a[i]=find(a[i]),++sum[a[i]];
	For(i,1,n)b[i]=find(b[i]),--sum[b[i]];
	/*For(i,1,n)cout<<a[i]<<' ';
	cout<<endl;
	For(i,1,n)cout<<b[i]<<' ';
	cot<<endl;*/
	For(i,1,m)pos[i]=find(pos[i]);
	For(i,1,tot)sum[i]+=sum[i-1];
	//For(i,1,tot)cout<<sum[i]<<endl;
	For(i,1,tot-1)dis[i]=q[i+1]-q[i];
	tim=sqrt(tot);
	if(tim==1)++tim;
	For(i,1,tot)
	{
		if(i%tim==1)st[++block]=i;
		if(i%tim==0||i==tot)ed[block]=i;
		bl[i]=block;
		e[i]=(node){sum[i],dis[i],i};
		//cout<<e[i].sum<<' '<<e[i].dis<<endl;
	}
	For(i,1,block)rebuild(i);
//	For(i,1,tot)cout<<e[i].sum<<' '<<e[i].dis<<endl;
//	puts("");
	//For(i,1,tot)cout<<i<<' '<<e[i].sum<<' '<<e[i].dis<<endl;
}
void update(int p,int v)
{
	For(i,bl[p],block)
	{
		if(st[i]<p)
		{
			For(j,p,ed[i])e[ac_pos[j]].sum+=v;
			rebuild(i);
		}
		else 
		{
			lazy[i]+=v;
			recal(i);
		}
	}
}
void work()
{
	write(ans,'\n');
	For(i,1,m)
	{
		update(a[car[i]],-1);
		a[car[i]]=pos[i];
		update(a[car[i]],1);
		write(ans,'\n');
	}
}
int main()
{
	file();
	input();
	init();
	work();
	return 0;
}
posted @ 2018-04-09 18:41  dyx_diversion  阅读(233)  评论(0编辑  收藏  举报