zoukankan      html  css  js  c++  java
  • bzoj 2989: 数列

    LINK:数列

    需要动一点脑子 考虑查询 暴力显然不行 考虑把绝对值拆开。

    当x<=y ax<=ay时 有 y-x+ay-ax<=k x+ax>=y+ay-k 可以发现在满足前两个条件下第三个条件是这样才会被统计贡献。

    剩下3种情况分别是 x+ax<=k+ay+y x-ax<=k+y-ay ax-x=k-y+ay

    可以发现 这个类似于三维偏序问题 我们进行三维数点即可 但是由于操作有时间关系 上CDQ的话就变成了四维偏序。

    直接KD tree即可。考虑修改操作 其实就是插入 由于历史版本还有我们不需要删除。

    考虑替罪羊树维护。

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define ld long double
    #define pb push_back
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define put(x) printf("%d
    ",x)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define pii pair<int,int> 
    #define F first
    #define S second
    #define mk make_pair
    #define mod 1000000007
    #define RE register
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    const db alpha=0.75;
    const int MAXN=110000;
    const int K=3;
    int n,Q,cnt,D,top,ans,root;
    char a[10];
    struct wy
    {
    	int l,r;
    	int mx[K],mn[K];
    	int d[K];//自己本身元素
    	int sum;
    }t[MAXN<<2];
    int q[MAXN<<2],b[MAXN];
    inline int cmp(int a,int b){return t[a].d[D]<t[b].d[D];}
    inline void pushup(int p)
    {
    	int l=t[p].l;int r=t[p].r;
    	t[p].sum=t[l].sum+t[r].sum+1;
    	rep(0,K-1,i)
    	{
    		if(l)t[p].mx[i]=max(t[l].mx[i],t[p].mx[i]),t[p].mn[i]=min(t[p].mn[i],t[l].mn[i]);
    		if(r)t[p].mx[i]=max(t[r].mx[i],t[p].mx[i]),t[p].mn[i]=min(t[p].mn[i],t[r].mn[i]);
    	}
    }
    inline int build(int l,int r,int k)
    {
    	if(l>r)return 0;
    	int mid=(l+r)>>1;D=k;
    	nth_element(q+l,q+mid,q+1+r,cmp);
    	rep(0,K-1,i)t[q[mid]].mx[i]=t[q[mid]].mn[i]=t[q[mid]].d[i];
    	t[q[mid]].l=build(l,mid-1,(k+1)%K);
    	t[q[mid]].r=build(mid+1,r,(k+1)%K);
    	pushup(q[mid]);return q[mid];
    }
    inline void dfs(int x)
    {
    	if(!x)return;
    	q[++top]=x;
    	if(t[x].l)dfs(t[x].l);
    	if(t[x].r)dfs(t[x].r);
    }
    inline void insert(int &p,int x,int k,int flag)
    {
    	if(!p)
    	{
    		p=x;t[p].sum=1;
    		rep(0,K-1,i)t[p].mx[i]=t[p].mn[i]=t[p].d[i];
    		return;
    	}
    	int mark=0;
    	if(t[x].d[k]<t[p].d[k])
    	{
    		if(t[t[p].l].sum>=t[p].sum*alpha)mark=1;
    		insert(t[p].l,x,(k+1)%K,flag|mark);
    	}
    	else
    	{
    		if(t[t[p].r].sum>=t[p].sum*alpha)mark=1;
    		insert(t[p].r,x,(k+1)%K,flag|mark);
    	}
    	if(mark&&!flag)top=0,dfs(p),p=build(1,top,k);
    	else pushup(p);
    }
    inline int check(int x)
    {
    	rep(0,K-1,i)if(t[x].mx[i]>q[i])return 0;
    	return 1;
    }
    inline int check_point(int x)
    {
    	rep(0,K-1,i)if(t[x].d[i]>q[i])return 0;
    	return 1;
    }
    inline int check_range(int x)
    {
    	rep(0,K-1,i)if(t[x].mn[i]>q[i])return 0;
    	return 1;
    }
    inline void ask(int x)
    {
    	if(check(x)){ans+=t[x].sum;return;}
    	if(check_point(x))++ans;
    	if(t[x].l&&check_range(t[x].l))
    		ask(t[x].l);
    	if(t[x].r&&check_range(t[x].r))
    		ask(t[x].r);
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(Q);
    	rep(1,n,i)
    	{
    		int x;get(x);b[i]=x;
    		t[++cnt].d[0]=i;t[cnt].d[1]=x;t[cnt].d[2]=-i-x;q[cnt]=cnt;
    		t[++cnt].d[0]=-i;t[cnt].d[1]=-x;t[cnt].d[2]=i+x;q[cnt]=cnt;
    		t[++cnt].d[0]=-i;t[cnt].d[1]=x;t[cnt].d[2]=i-x;q[cnt]=cnt;
    		t[++cnt].d[0]=i;t[cnt].d[1]=-x;t[cnt].d[2]=x-i;q[cnt]=cnt;
    	}
    	root=build(1,cnt,0);
    	rep(1,Q,i)
    	{
    		scanf("%s",a+1);
    		if(a[1]=='M')
    		{
    			int x,y;get(x);get(y);b[x]=y;
    			t[++cnt].d[0]=x;t[cnt].d[1]=y;t[cnt].d[2]=-x-y;insert(root,cnt,0,0);
    			t[++cnt].d[0]=-x;t[cnt].d[1]=-y;t[cnt].d[2]=y+x;insert(root,cnt,0,0);
    			t[++cnt].d[0]=-x;t[cnt].d[1]=y;t[cnt].d[2]=x-y;insert(root,cnt,0,0);
    			t[++cnt].d[0]=x;t[cnt].d[1]=-y;t[cnt].d[2]=y-x;insert(root,cnt,0,0);
    		}
    		else
    		{
    			ans=0;int x,y;get(x);get(y);
    			//x<=y ax<=ay -x-ax<=-y-ay+k 也统计x相等y相等
    			q[0]=x;q[1]=b[x];q[2]=-x-b[x]+y;ask(root);
    			//x>=y ax>ay x+ax<=k+ay+y
    			q[0]=-x;q[1]=-b[x]-1;q[2]=x+b[x]+y;ask(root);
    			//x>y ax<=ay x-ax<=k+y-ay
    			q[0]=-x-1;q[1]=b[x];q[2]=y+x-b[x];ask(root);
    			//x<y ax>=ay -x+ax<=k+ay-y;
    			q[0]=x-1;q[1]=-b[x];q[2]=y+b[x]-x;ask(root);
    			put(ans);
    		}
    	}
    	return 0;
    }
    

    代码写的有问题 我这样做应该建立四棵KD-tree。

    或者 写四个ask 我觉得。

    网上题解都是旋转坐标系转契比雪夫距离了。我思考一下我这种做法对不对。

  • 相关阅读:
    微软ASP.NET网站部署指南(4):配置项目属性
    iOS 设计模式之抽象工厂
    How can I move a MySQL database from one server to another?
    CentOS 7 上安装vim(默认未安装)
    How to resize slide dimensions without resizing any objects on the slide?
    CentOS 7.3 上安装docker
    美国留学访学(访问学者)必备信用卡
    西安理工大学税务登记证、银行账号信息
    Oracle联合多个子查询(inner join)
    linux tail
  • 原文地址:https://www.cnblogs.com/chdy/p/12533032.html
Copyright © 2011-2022 走看看