zoukankan      html  css  js  c++  java
  • BZOJ2989: 数列

    题解: 根据题面公式将题目转化成二维平面问题 可持久话不是真的可持久化 只需要将以前修改的点一并放在二维平面中即可  然后问题转化为求二维平面斜正方形里面包含的节点数 然而斜正方形往下搜的复杂度会退化到n^2 所以我们考虑将坐标系旋转一下 然后查询正方形内的节点个数  (挂价函数写挂了 一直WA 气气~~~

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=1e5+10;
    const double eps=1e-8;
    const int inf=1e9;
    #define ll long long
    using namespace std;
    struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int rt,d,n,q;
    typedef struct node{
    	int p[2],maxx[2],minn[2],c[2],sz;
    	friend bool operator<(node aa,node bb){
    		if(aa.p[d]!=bb.p[d])return aa.p[d]<bb.p[d];
    		return aa.p[d^1]<bb.p[d^1];
    	}
    }node;
    node a[MAXN];int b[MAXN];
    void up(int x){
    	int l=a[x].c[0];int r=a[x].c[1];
    	for(int i=0;i<=1;i++)a[x].minn[i]=a[x].maxx[i]=a[x].p[i];
    	for(int i=0;i<=1;i++)a[x].minn[i]=min(a[x].minn[i],a[l].minn[i]),a[x].maxx[i]=max(a[x].maxx[i],a[l].maxx[i]);
    	for(int i=0;i<=1;i++)a[x].minn[i]=min(a[x].minn[i],a[r].minn[i]),a[x].maxx[i]=max(a[x].maxx[i],a[r].maxx[i]);
    	a[x].sz=a[a[x].c[0]].sz+a[a[x].c[1]].sz+1;
    }
    int built(int l,int r,int now){
    	int mid=(l+r)>>1;
    	d=now;nth_element(a+l,a+mid,a+r+1);
    	for(int i=0;i<=1;i++)a[mid].minn[i]=a[mid].maxx[i]=a[mid].p[i];
    	a[mid].c[0]=a[mid].c[1]=0;a[mid].sz=0;
    	if(l<mid)a[mid].c[0]=built(l,mid-1,now^1);
    	if(r>mid)a[mid].c[1]=built(mid+1,r,now^1);
    	up(mid);
    	return mid;
    }
    void insert(int &k , int x)
    {
        if(!k) k = x;
        else if(a[x] < a[k]) d ^= 1 , insert(a[k].c[0] , x);
        else d ^= 1 , insert(a[k].c[1] , x);
        up(k);
    }
    int ans;
    void querty(int x,int x1,int y1,int x2,int y2){
    	if(!x)return ;
    	if(x2<a[x].minn[0]||x1>a[x].maxx[0]||y2<a[x].minn[1]||y1>a[x].maxx[1])return ;
    	if(x1<=a[x].minn[0]&&x2>=a[x].maxx[0]&&y1<=a[x].minn[1]&&y2>=a[x].maxx[1]){ans+=a[x].sz;return ;}
    	if(a[x].p[0]>=x1&&a[x].p[0]<=x2&&a[x].p[1]>=y1&&a[x].p[1]<=y2){ans++;}
    	querty(a[x].c[0],x1,y1,x2,y2);
    	querty(a[x].c[1],x1,y1,x2,y2);
    }
    char str[11];
    int main(){
    	a[0].minn[0]=a[0].minn[1]=inf;a[0].maxx[0]=a[0].maxx[1]=-inf;
    	n=read();q=read();int tot=n;
    	int t,x,k;
    	for(int i=1;i<=n;i++){b[i]=t=read();a[i].p[0]=i-t;a[i].p[1]=i+t;}
    	rt=built(1,n,0);
    	while(q--){
    		scanf("%s",str);x=read();k=read();
    		if(str[0]=='Q'){ans=0;querty(rt,x-k-b[x],x-k+b[x],x+k-b[x],x+k+b[x]);printf("%d
    ",ans);}
    		else{
    			tot++;a[tot].c[0]=a[tot].c[1]=0;a[tot].sz=0;
    			a[tot].p[0]=a[tot].minn[0]=a[tot].maxx[0]=x-k;
    			a[tot].p[1]=a[tot].minn[1]=a[tot].maxx[1]=x+k;
    			b[x]=k;
    			insert(rt,tot);
    			//if(tot%10000==0)built(1,tot,0);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    POJ 2411 状态压缩递,覆盖方案数
    POJ 2774 最长公共子串
    POJ 1743 不可重叠的最长重复子串
    POJ 3294 出现在至少K个字符串中的子串
    POJ 3261 出现至少K次的可重叠最长子串
    POJ 1741/1987 树的点分治
    HDU1556 Color the ball
    解决linux系统时间不对的问题
    CentOS 6.9使用Setup配置网络(解决dhcp模式插入网线不自动获取IP的问题)
    Linux网络配置(setup)
  • 原文地址:https://www.cnblogs.com/wang9897/p/9714825.html
Copyright © 2011-2022 走看看