“若是万一琪露诺(俗称 rhl)进行攻击,什么都好,冷静地回答她的问题来吸引
对方表现出兴趣的话,那就慢慢地反问。在她考虑答案的时候,趁机逃吧。就算是很简
问题,她一定也答不上来。” ——《上古之魔书》
天空中出现了许多的北极光,这些北极光组成了一个长度为n的正整数数列 a[i],远
魔书上记载到:2 个位置的 graze 值为两者位置差与数值差的和:
graze(x,y)=|x-y|+|a[x]-a[y]|。
要想破解天罚,就必须支持 2种操作(k 都是正整数):
Modify x k:将第 x个数的值修改为k。
Query x k:询问有几个 i满足graze(x,i)<=k。
由于从前的天罚被圣王lmc破解了,所以rhl改进了她的法术,询问不仅要考虑当
列,还要考虑任意历史版本,即统计任意位置上出现过的任意数值与当前的a[x]的 graz
<=k的对数。(某位置多次修改为同样的数值,按多次统计)
第1行两个整数 n,q。分别表示数列长度和操作数。
第2行 n个正整数,代表初始数列。
第3~q+2 行每行一个操作。
对于每次询问操作,输出一个非负整数表示答案。
3 5
2 4 3
Query 2 2
Modify 1 3
Query 2 2
Modify 1 2
Query 1 1
2
3
3
题解:
出题人的题解真是简单(虽然题目也很简单)
“直接线段树套平衡树就可以了”
傻逼k-d树调了快俩小时,这搞腿子。
因为询问是与给定点的曼哈顿距离小于给定值的点个数,这个可以把坐标转换一下,像这样:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int inf=300005;
int getint()
{
int f=1,g=0;char c=getchar();
while(c<‘0‘ || c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
while(c<=‘9‘ && c>=‘0‘)g=(g<<3)+(g<<1)+c-‘0‘,c=getchar();
return f*g;
}
int n;
int q;
namespace brute_force{
const int maxn=200005;
vector<int> a[maxn];
int b[maxn];
bool check()
{
return q<=99;
}
char opt[20];
void solve()
{
for(int i=1;i<=n;i++)
{
a[i].push_back(getint());
b[i]=a[i][0];
}
int x,y;
for(int i=1;i<=q;i++)
{
scanf("%s",opt);
if(opt[0]==‘M‘)
{
x=getint();
y=getint();
a[x].push_back(y);
b[x]=y;
}
if(opt[0]==‘Q‘)
{
x=getint();
y=getint();
int cnt=0;
for(int j=1;j<=n;j++)
{
for(int l=0;l<a[j].size();l++)
{
if(abs(x-j)+abs(b[x]-a[j][l])<=y)
{
cnt++;
}
}
}
printf("%d\n",cnt);
}
}
}
}
namespace another_brute_force{
const int maxn=160005;
struct node{
int d[2];
int min[2];
int max[2];
int cnt;
int size;
int l,r;
int& operator [] (const unsigned int& num)
{
return d[num];
}
};
node t[maxn];
node p[maxn];
int dim;
int tot;
#define ls t[x].l
#define rs t[x].r
#define lc t[t[x].l]
#define rc t[t[x].r]
#define mid (l+r>>1)
bool cmp (const node& n1,const node& n2)
{
return n1.d[dim]<n2.d[dim];
}
struct kd_tree
{
node T;
int root;
void update(int x)
{
t[x].size=t[x].cnt;
t[x].min[0]=t[x].max[0]=t[x][0];
t[x].min[1]=t[x].max[1]=t[x][1];
for(int i=0;i<2;i++)
{
if(ls)
{
t[x].max[i]=max(t[x].max[i],lc.max[i]);
t[x].min[i]=min(t[x].min[i],lc.min[i]);
}
if(rs)
{
t[x].max[i]=max(t[x].max[i],rc.max[i]);
t[x].min[i]=min(t[x].min[i],rc.min[i]);
}
}
if(ls)t[x].size+=lc.size;
if(rs)t[x].size+=rc.size;
}
/**/
void build(int &x,int l,int r,int now)
{
if(l>r)return;
dim=now;
nth_element(p+l,p+mid,p+r,cmp);
x=mid;
t[x].cnt=1;
t[x].size=1;
for(int i=0;i<2;i++)
{
t[x][i]=t[x].min[i]=t[x].max[i]=p[x][i];
}
build(ls,l,mid-1,now^1);
build(rs,mid+1,r,now^1);
update(x);
}
void insert(int& x,int now)
{
if(!x)
{
x=++tot;
t[x]=T;
return;
}
if(T[0]==t[x][0] && T[1]==t[x][1])
{
t[x].cnt++;
t[x].size++;
return;
}
if(T[now]>t[x][now])
{
insert(rs,now^1);
update(x);
}
else
{
insert(ls,now^1);
update(x);
}
}
int k;
int The_Answer;
/*
bool check(int x)
{
int left=T[0]-k;
int right=T[0]+k;
int up=T[1]+k;
int down=T[1]-k;
if(down>t[x].max[1] || up<t[x].min[1] || left>t[x].max[0] || right<t[x].min[0])
return false;
return true;
}
int get(int x)
{
int left=T[0]-k;left=max(0,t[x].max[0]-left);
int right=T[0]+k;right=max(0,right-t[x].min[0]);
int up=T[1]+k;up=max(0,up-t[x].min[1]);
int down=T[1]-k;down=max(0,t[x].max[1]-down);
return min(min(left,right),min(up,down));
}
void query(int x)
{
if(!x)return;
if(max(abs(t[x].min[0]-T[0])+abs(t[x].min[1]-T[1]),abs(t[x].max[0]-T[0])+abs(t[x].max[1]-T[1]))<=k
&& max(abs(t[x].min[0]-T[0])+abs(t[x].max[1]-T[1]),abs(t[x].min[1]-T[1])+abs(t[x].max[0]-T[0]))<=k)
{
The_Answer+=t[x].size;
return;
}
/*
if(min(abs(t[x].min[0]-T[0])+abs(t[x].min[1]-T[1]),abs(t[x].max[0]-T[0])+abs(t[x].max[1]-T[1]))>k
&& min(abs(t[x].min[0]-T[0])+abs(t[x].max[1]-T[1]),abs(t[x].min[1]-T[1])+abs(t[x].max[0]-T[0]))>k
&&(t[x].min[0]>T[0] || t[x].max[0]<T[0] || t[x].min[1]<T[1] || t[x].max[1]>T[1]))
*
if(!check(x))
{
return;
}
if(abs(t[x][0]-T[0])+abs(t[x][1]-T[1])<=k)
{
The_Answer+=t[x].cnt;
}
/*
int tl=min( min(abs(lc.min[0]-T[0])+abs(lc.min[1]-T[1]),abs(lc.max[0]-T[0])+abs(lc.max[1]-T[1])),
min(abs(lc.min[0]-T[0])+abs(lc.max[1]-T[1]),abs(lc.max[0]-T[0])+abs(lc.min[1]-T[1])));
int tr=min( min(abs(rc.min[0]-T[0])+abs(rc.min[1]-T[1]),abs(rc.max[0]-T[0])+abs(rc.max[1]-T[1])),
min(abs(rc.min[0]-T[0])+abs(rc.max[1]-T[1]),abs(rc.max[0]-T[0])+abs(rc.min[1]-T[1])));
*
int tl=get(ls);
int tr=get(rs);
if(tl<=tr)
{
if(tl<=k)query(ls);
if(tr<=k)query(rs);
}
else
{
if(tr<=k)query(rs);
if(tl<=k)query(ls);
}
}
*/
node T1,T2;
void query(int x)
{
if(!x)return;
if(t[x].max[0]<T1[0] || t[x].min[0]>T2[0] || t[x].max[1]<T1[1] || t[x].min[1]>T2[1])return;
if(t[x].max[0]<=T2[0] && t[x].min[0]>=T1[0] && t[x].max[1]<=T2[1] && t[x].min[1]>=T1[1])
{
The_Answer+=t[x].size;
return;
}
if(t[x][0]>=T1[0] && t[x][0]<=T2[0] && t[x][1]>=T1[1] && t[x][1]<=T2[1])
{
The_Answer+=t[x].cnt;
}
int tl=min(min(abs(T1[0]-lc.max[0]),abs(T2[0]-lc.min[0])),min(T1[1]-lc.max[1],T2[1]-lc.min[1]));
int tr=min(min(abs(T1[0]-rc.max[0]),abs(T2[0]-rc.min[0])),min(T1[1]-rc.max[1],T2[1]-rc.min[1]));
if(tl<=tr)
{
if(tl<=k)query(ls);
if(tr<=k)query(rs);
}
else
{
if(tr<=k)query(rs);
if(tl<=k)query(ls);
}
}
void ins(int x,int y)
{
T[0]=T.min[0]=T.max[0]=x;
T[1]=T.min[1]=T.max[1]=y;
T.size=T.cnt=1;
T.l=T.r=0;
insert(root,0);
}
int que(int x,int y,int kk)
{
T1[0]=max(-inf,x-kk);
T2[0]=min(inf,x+kk);
T1[1]=max(-inf,y-kk);
T2[1]=min(inf,y+kk);
k=kk;The_Answer=0;
query(root);
return The_Answer;
}
}kdtree;
int b[maxn];
char opt[20];
void solve()
{
kdtree.The_Answer=0;
for(int i=1;i<=n;i++)
{
b[i]=getint();
//kdtree.ins(i+b[i],i-b[i]);
p[i][0]=i+b[i];
p[i][1]=i-b[i];
}
kdtree.build(kdtree.root,1,n,0);
tot=n;
int x,y;
for(int i=1;i<=q;i++)
{
scanf("%s",opt);
if(i==10000)
{
i++;
i--;
}
if(opt[0]==‘Q‘)
{
x=getint();
y=getint();
printf("%d\n",kdtree.que(x+b[x],x-b[x],y));
}
else
{
x=getint();
y=getint();
b[x]=y;
kdtree.ins(x+b[x],x-b[x]);
}
}
}
}
//expected score 100
int main()
{
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
n=getint();
q=getint();
/**/
if(brute_force::check())
{
brute_force::solve();
}
else
/**/
{
another_brute_force::solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/starry__night/article/details/46794135