题面
题目描述
高中,高中,短暂的三年。NOI是高中结业考试,而高考在每年暑假举行。
高二暑假,这是你最后一次参加高考的机会。你已经为了高考停课很久了,OI的知识很久没管了。你并没有能力用一年时间补起别人三年的OI课程。这是你的最后一战,如果你失败了,可能就不能工地搬砖只能去清华了。
这天你背上行囊赴京赶考。此时全国交通主要靠瞬间传送装置。全国交通网络可以抽象为一张n行 m列的网格图。行依次编号为 1,…,n,列依次编号为 1,…,m。
有 n+m 个为 0 或 1 的整数 a1,…,an,b1,…,bm。对于 1≤i≤n,1≤j≤m,如果 ai=bj 那么网格图上第 i 行第 j列上标着 0 否则标着 1。
你的家在第 xs 行第 ys 列,高考考场在第 xe 行第 ye 列。现在你想从家出发到高考考场去。每次你可以:
向上移动一行。(如果你在第一行那么移动后会到最后一行去)
向下移动一行。(如果你在最后一行那么移动后会到第一行去)
向左移动一列。(如果你在第一列那么移动后会到最后一列去)
向右移动一列。(如果你在最后一列那么移动后会到第一列去)
对于每次移动,如果移动前的格子上标的数跟移动后的格子上标的数不同,那么就要耗费 1 分钟时间等待瞬移装置调整配置,否则不耗时间。
现在你想知道你从家出发到高考考场最少需要花多长时间。
输入格式
第一行两个正整数 n,m,表示网格图为 n 行 m 列。
第二行 n 个整数,分别表示 a1,…,an。保证 a1,…,an∈{0,1}。
第三行 m 个整数,分别表示 b1,…,bm。保证 b1,…,bm∈{0,1}。
接下来一个正整数 q。
接下来 q 行,每行四个整数 xs,ys,xe,ye。表示询问如果你的家在第 xs 行第 ys 列,高考考场在第 xe 行第 ye 列时的最少花费时间。
输出格式
共 q 行,每行一个整数表示最少花费多少分钟。
样例输入
1 2 3 4 5 6
| 1 2 1 0 1 2 1 2 1 2 1 1 1 2
|
样例输出
数据规模与约定
对于30%的数据,n,m≤100,q≤10
对于另外20%的数据,n,q≤100000,m=1
对于100%的数据,n,m,q≤100000
题解
思路
仔细观察,就会发现对于每行或每列,与当前所在行/列无关,只与 ai 或 bi 有关。
所以我们将每列和每行分别求经过边界到达和直接到达的最小值。
直接每次都暴力求一遍是肯定会超时的,我们可以将a数组和b数组做一个前缀和,然后就可以O(1)的时间复杂度应对询问。
代码实现
时间复杂度O(n+m+q)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include<iostream> #include<array> #include<algorithm> #include<cmath> #include<vector> #include<bitset> using namespace std; using gg=long long; bitset<100010> a,b; array<gg,100010> aa,bb; inline gg rd(){ char ch=getchar();gg x=0; while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } inline bool getval(const gg &x,const gg &y){ return a[x]==b[y]?0:1; } int main(){ gg n,m,q,xs,ys,xt,yt,tp1,tp2; n=rd(),m=rd(); char ch=getchar(); for(gg i=1;i<=n;i++){ while(ch<'0'||ch>'1') ch=getchar(); a[i]=ch-'0'; ch=getchar(); } if(a[1]!=a[n]) aa[1]=1; else aa[1]=0; for(gg i=2;i<=n;i++){ if(a[i]!=a[i-1]) aa[i]=aa[i-1]+1; else aa[i]=aa[i-1]; } for(gg i=1;i<=m;i++){ while(ch<'0'||ch>'1') ch=getchar(); b[i]=ch-'0'; ch=getchar(); } if(b[1]!=b[m]) bb[1]=1; else bb[1]=0; for(gg i=2;i<=m;i++){ if(b[i]!=b[i-1]) bb[i]=bb[i-1]+1; else bb[i]=bb[i-1]; }
q=rd(); while(q--){ tp1=0,tp2=0; xs=rd(),ys=rd(),xt=rd(),yt=rd(); if(xs<xt){ tp1=min(aa[xt]-aa[xs],aa[n]-aa[xt]+aa[xs]); } else if(xs>xt){ swap(xs,xt); tp1=min(aa[xt]-aa[xs],aa[n]-aa[xt]+aa[xs]); swap(xs,xt); } if(ys<yt){ tp2=min(bb[yt]-bb[ys],bb[m]-bb[yt]+bb[ys]); } else if(ys>yt){ swap(ys,yt); tp2=min(bb[yt]-bb[ys],bb[m]-bb[yt]+bb[ys]); swap(ys,yt); } cout<<tp1+tp2<<'\n'; } return 0; }
|
总结
题本身不是很难,只要发现了这个地图的特殊性即可做出。
6月份就考过,当时也没改这道题,这次考试看了半天才想出来,发个博客记录一下。