题意:

给出一N*N的蛇形矩阵,具体位置元素值不给你,自己找规律,然后给你M个

有效位置,P次查询,每次查询一个子矩阵中有效元素的权值和,该权值和等于对于

每个有效元素,模10拆分后相加得到的和。(注意有效点以及询问x、y所代表的含义,

是x轴,y轴)。

input
1
3 4 4
1 1
2 2
3 3
2 3
1 1 1 1
2 2 3 3
1 1 3 3
1 2 2 3

output

5
18
23
17

思路:

   第一个难点在于回旋矩阵给出x,y坐标让我们求对应值,找规律写通项公式。

其次查询二维区间和的难点在于10^6*10^6的矩阵无法表示,用map空间上可以,

但是map修改操作带个log,所以会超时,即使是用二维树状数组。不信看下面的超时代码。

比赛时自己的想法很接近正确思路,离线然后树状数组维护,但是因为这种题目做的

比较少,知识点不够熟练,所以没能写出来

比赛思考如下,因为有过见过一些类似题目(见过,代码实现的基本没有),所以

很容易往离线查询上想,然后树状数组维护。因为考虑到1e6*1e6的矩阵大小,但有效点最多

只有1e6个,所以想到降维处理,二维变为一维,然后对于每一次查询,有两个限制因素,一个

在x轴上,一个在y轴上,不难想到如果我们将所有有效点按x从小到大排序,那么现在对于

每次询问来说,只需要考虑在L,R(L,R很容易确定)的连续区间内,y值位于限定范围内

的那些离散的元素即可(事实证明这里的L,R没啥实质作用,只是思考的过程产生的想法)。

显然我们的BIT要建立在y的值域上,并按照x轴顺序不断更新BIT,在当前x位置,前x列的元素

都已经被添加,所以我们可以查询任意y区间的区间和,但注意,这里求出的y的区间和是对于

1~x所有列来说的,而并不是我们所需要的 x 范围。(比赛中bug就在这里,没有考虑到去重,

通过样例发现问题后也没有想到合适的解决办法)。

一个很巧妙的解决方法是每个询问拆成两部分,两者均为1~对应x的前缀统计(差分公式拆分)。

只不过一个为正数,一个为负数,这样每次询问的答案就由两个询问共同组成。

再仔细考虑离线查询的过程,我们是先枚举有效点,然后移动询问,还是先枚举询问再移动有效点。

自己当时写的代码采取了第一种方案,但自己写的有很大bug,当x1位置被更新后,我们要计算所有

位于x1和x2之间的询问,(而不仅仅是x1相关的询问,比赛时的bug)。*****(所以说理论上两种枚举方

案都可以,不过本题第一种方案麻烦一点,要对最后一个有效位置单独处理)。看了题解大都第二种方案,

直接枚举询问,对于当前询问,把它前面所有的有效位置全部更新,这样就不用特殊处理了,较方便

引申......上面对于询问的拆分,难道不就是线段树优化扫描线时的方法么,拆分后的项由1个x,2个y

(或1个y,2个x)组成,权值分别为1和-1 ... ...

有大佬 直接利用二维差分前缀和的公式,将一次查询拆分为四次查询:

 。

然后直接按照x的顺序依次统计相应y的数量即可。虽然这样的拆分是多余的,因为只要x或者y一

者被拆分,另一者完全可以通过前缀和求解给定L,R的权值和,且无遗漏无重复。(或者说造成:

如按x排序,bit针对y轴,造成y冗余的原因是因为x的冗余,所以对x拆分即可)。但是4项拆分思

维量对目前水平的自己来说看起来好像思维量小好多,关键在于理解好4项拆分为什么是正确的?

代码实现(二维树状数组TLE):

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>#define inf 0x3f3f3f3f
#define LL long longusing namespace std;const int N = 1e6 + 100;
map<int,long long>bit[N];
int xx[N],yy[N],tot;
void add(int x,int y,long long val,int n) {for(int i=x; i<=n; i+=i&-i) {for(int j=y; j<=n; j+=j&-j) {bit[i][j]+=val;xx[++tot]=i;yy[tot]=j;}}
}
long long qu(int x,int y) {long long res = 0;for(int i=x; i; i-=i&-i)for(int j=y; j; j-=j&-j) {res+=bit[i][j];}return res;
}LL sol(LL n, LL x, LL y) {LL qs = n / 2, q = min(n - y + 1, min(n - x + 1, min(x, y))) - 1;if (x == qs + 1 && y == qs + 1)   return n * n;LL ans = 1ll * q * (8 * qs + 8 * (qs - q + 1)) / 2;if (n - x == q)    ans += n - q - y + 1;else if (y - 1 == q)ans += n - 2 * q + 1 + n - q - 1 - x;else if (x - 1 == q)ans += n - 2 * q + 1 + n - 2 * q - 2 + y - q - 1;else ans += n - 2 * q + 1 + n - 2 * q - 2 + n - 2 * q - 1 + x - q - 1;return ans;
}
int main() {
#ifdef MYHOME_Wjvjefreopen("input.txt","r",stdin);
#endifint t;//cout<<(sizeof(bit))/1024<<endl;scanf("%d",&t);while(t--) {while(tot)bit[xx[tot]][yy[tot]]=0,tot--;int n,m,p;scanf("%d%d%d",&n,&m,&p);int x,y;//TLEfor(int i=1; i<=m; i++) {int x,y;scanf("%d%d",&x,&y);add(x,y,sol(n,x,y),n);}//TLE too...for(int i=1; i<=p; i++) {int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);printf("%lld\n",qu(x2,y2)-qu(x1,y1-1)-qu(x1-1,y1)+qu(x1-1,y1-1));}}return 0;
}

两项拆分离线AC代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;const int N = 2e5+100;
const int M = 4e5+100;struct Node {int r,c;long long val;
} arr[N];
bool cmp1(Node aa,Node bb) {return aa.r<bb.r;
}
bool cmp2(Node aa,Node bb) {return aa.c<bb.c;
}
//回旋矩阵O(1)求值
LL sol1(LL n, LL x, LL y) {x=x-n/2-1;y=y-n/2-1;long long tmp=max(abs(x),abs(y)),ans;if(x>=y)ans=n*n-4*tmp*tmp-2*tmp-x-y;else ans=n*n-4*tmp*tmp+2*tmp+x+y;return ans;
}long long sol2(long long x) {long long res=0;while(x) {res+=x%10;x/=10;}return res;
}struct query {int x1,y1,x2,y2,id;int val;
} qrr[N];
bool cmp3(query aa,query bb) {return aa.x2<bb.x2;
}int bst[N],ans[N];
void update(int x,int v,int n) {for(; x<=n; x+=x&-x)bst[x]+=v;
}
int qu(int x) {int res=0;for(; x; x-=x&-x)res+=bst[x];return res;
}
int main() {
#ifdef MYHOME_Wjvjefreopen("input.txt","r",stdin);
#endifint t,n,m,p,tot;int x,y;scanf("%d",&t);while(t--) {tot=0;memset(bst,0,sizeof(bst));memset(ans,0,sizeof(ans));scanf("%d%d%d",&n,&m,&p);for(int i=1; i<=m; i++) {scanf("%d%d",&x,&y);arr[i].r=x;arr[i].c=y;arr[i].val=sol2(sol1(n,x,y));}sort(arr+1,arr+1+m,cmp1);for(int i=1; i<=p; i++) {scanf("%d%d",&qrr[i].x1,&qrr[i].y1);scanf("%d%d",&qrr[i].x2,&qrr[i].y2);qrr[i].id=i;qrr[i].val=1;qrr[i+p].id=i;qrr[i+p].val=-1;qrr[i+p].y1=qrr[i].y1;//1个 x对 2个 y.qrr[i+p].y2=qrr[i].y2;qrr[i+p].x2=qrr[i].x1-1;}sort(qrr+1,qrr+1+p*2,cmp3);int pw=1;//先枚举查询,另一种枚举理论上可行for(int i=1; i<=p*2; i++) {while(pw<=m&&arr[pw].r<=qrr[i].x2)update(arr[pw].c,arr[pw].val,n),pw++;ans[qrr[i].id]+=qrr[i].val*(qu(qrr[i].y2)-qu(qrr[i].y1-1));}for(int i=1; i<=p; i++)printf("%d\n",ans[i]);}return 0;
}

四项拆分离线AC代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>using namespace std;const int N = 1e5+100;struct Node {int x,y;long long val;bool operator <(const Node & obj)const {return x<obj.x;}
} arr[N];
//回旋矩阵求值
long long sol1(long long n,long long x,long long y) {x=x-n/2-1;y=y-n/2-1;long long tmp=max(abs(x),abs(y)),ans;if(x>=y)ans=n*n-4*tmp*tmp-2*tmp-x-y;else ans=n*n-4*tmp*tmp+2*tmp+x+y;return ans;
}
long long sol2(long long x) {long long res=0;while(x) {res+=x%10;x/=10;}return res;
}struct query {int x,y,id,val;bool operator <(const query & obj)const {return x<obj.x;}
} qrr[4*N];long long bst[N],ans[N];
void update(int x,int v,int n) {for(; x<=n; x+=x&-x)bst[x]+=v;
}
long long qu(int x) {long long res=0;for(; x; x-=x&-x)res+=bst[x];return res;
}
int main() {
#ifdef MYHOME_Wjvjefreopen("input.txt","r",stdin);
#endifint t,n,m,p;int x,y;scanf("%d",&t);while(t--) {memset(bst,0,sizeof(bst));memset(ans,0,sizeof(ans));scanf("%d%d%d",&n,&m,&p);for(int i=1; i<=m; i++) {scanf("%d%d",&x,&y);arr[i].x=x;arr[i].y=y;arr[i].val=sol2(sol1(n,x,y));}sort(arr+1,arr+1+m);for(int i=1; i<=p; i++) {int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);//sum=map[x2][y2]−map[x2][y1−1]−map[x1−1][y2]+map[x1−1][y1−1]qrr[i]=query {x2,y2,i,1};qrr[i+p]=query {x1-1,y2,i,-1};qrr[i+2*p]=query {x2,y1-1,i,-1};qrr[i+3*p]=query {x1-1,y1-1,i,1};}sort(qrr+1,qrr+1+p*4);int pw=1;//离线for(int i=1; i<=p*4; i++) {while(pw<=m&&arr[pw].x<=qrr[i].x)update(arr[pw].y,arr[pw].val,n),pw++;ans[qrr[i].id]+=qrr[i].val*qu(qrr[i].y);}for(int i=1; i<=p; i++)printf("%lld\n",ans[i]);}return 0;
}

THE END;

2019 南京 网络赛 B (二维偏序,树状数组离线)相关推荐

  1. HDU2642(二维的树状数组)

    二维的树状数组,我记得是模版!^ _ ^ 题意很清楚:就是这部分的原理:sum(x1,y1)+sum(x2-1,y2-1)-sum(x1,y2-1)-sum(x2-1,y1);其实可以和概率论中的一个 ...

  2. 洛谷 - P2163 [SHOI2007]园丁的烦恼(不带修二维数点-树状数组/主席树)

    题目链接:点击查看 题目大意:二维平面坐标系中给出 nnn 个坐标点,然后是 mmm 次询问,每次询问需要回答一个闭合矩阵中有多少个点 题目分析:想挂树套树来着,但是复杂度有点大.本题不带修且可以离线 ...

  3. 二维树状数组 ----2021广东省赛 ----- K - Kera‘s line segment[区间转二维平面+树状数组维护前缀最小最大值]

    题目链接 题目大意: 就是一个一维的数轴上面有一堆线段用一个三元组(l,r,val)(l,r,val)(l,r,val)表示. 现在我们有两个操作: 就是往数轴上面添加线段 询问[L,R][L,R][ ...

  4. 【2019.09.01】2019南京网络赛

    补题地址:https://www.jisuanke.com/contest/3004?view=challenges A: B: C: D: E: F:✅ G: H:✅ I: 转载于:https:// ...

  5. The beautiful values of the palace(2019南京网络赛)

    题目链接:https://nanti.jisuanke.com/t/41298 题意:给一个n * n的螺旋矩阵,n保证是奇数,取一些点使其.获得价值,价值为数位和,然后再给q次查询,求矩阵中的价值总 ...

  6. Holy Grail 2019南京网络赛

    https://nanti.jisuanke.com/t/41305 给定一个有向无负环图,然后告诉你要依次加6条边,要保证每次加边后无负环,求依次加边时保证当前边最小. 由于题目保证有解,所以s-& ...

  7. 【2018ACM山东省赛 - E】Sequence(树状数组,思维,优化)

    题干: We define an element aia_iai​ in a sequence "good", if and only if there exists a j(1≤ ...

  8. ACM-ICPC 2018 徐州赛区网络预赛 I. query 树状数组

    I. query 题目链接: Problem Description Given a permutation \(p\) of length \(n\), you are asked to answe ...

  9. YbtOJ#20237-[冲刺NOIP2020模拟赛Day10]区间均值【树状数组】

    正题 题目链接:https://www.ybtoj.com.cn/contest/68/problem/1 题目大意 nnn个数字的序列,求有多少个区间[l,r][l,r][l,r]的平均值在[L,R ...

最新文章

  1. 执行高性能任务的强大桌面计算机是,用于高性能任务的强大的桌面计算机是一个______。...
  2. python可以修图吗_会照片处理的不只是ps,还有Python!
  3. java断点续传上传_java断点续传上传文件,突然关闭然后再上传文件为什么不是从之前上传的进度上传...
  4. dos显示磁盘剩余空间
  5. 17、HTML单选按钮
  6. 基于c#的相关性分析_开源Math.NET基础数学类库使用(11)C#计算相关系数
  7. 210. 课程表 II
  8. linux系统内核参数配置优化,Linux服务器内核参数优化
  9. Data Analysis: What are the skills needed to become a data analyst?
  10. dubbo内置哪几种服务容器_Dubbo服务提供者几种启动方式
  11. (38)VHDL实现主从JK触发器
  12. oracle gg 有两个字段没同步到,GG配置Oracle同步到SQLServer
  13. linux入门常识(三)
  14. paip.中文 分词 ---paoding 3.1 的使用
  15. C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)
  16. DSP28335学习记录(三)——ePWM
  17. Python黑帽子_hack与渗透测试编程之道 第三章代码
  18. 一文读懂电子材料行业最新发展趋势
  19. standard-version(发版与 Changelog 自动化)
  20. 中国牛市短线炒股有哪些特征中国牛市炒股如何操作呢

热门文章

  1. Postgresql日期转字符串
  2. 机器学习——从线性回归到逻辑回归【附详细推导和代码】
  3. 谷歌地球不能用?国产谷歌地球替代软件提前转正
  4. ffmpeg 之 RTSP 一
  5. x299服务器芯片组,【装机帮扶站】第770期:X79/X99/X299平台“高级”垃圾简析
  6. 会议录音转文字(PC版)
  7. 宁波市教育学院计算机系主任,欢迎宁波诺丁汉大学计算机系主任白瑞斌教授一行到访南科大...
  8. 百度网盘真实地址解析(告别下载百度网盘)--修改版
  9. 完成端口 完成端口 完成端口 还是完成端口
  10. 支持向量机 (SVM)算法的原理及优缺点