ACM-ICPC 2018 徐州赛区(网络赛)
A. Hard to prepare
After Incident, a feast is usually held in Hakurei Shrine. This time Reimu asked Kokoro to deliver a Nogaku show during the feast. To enjoy the show, every audience has to wear a Nogaku mask, and seat around as a circle.
There are N guests Reimu serves. Kokoro has 2^k masks numbered from 0,1,⋯, 2^k-1, and every guest wears one of the masks. The masks have dark power of Dark Nogaku, and to prevent guests from being hurt by the power, two guests seating aside must ensure that if their masks are numbered i and j, then i XNOR j must be positive. (two guests can wear the same mask). XNOR means ~(i^j) and every number has kk bits. (1 XNOR 1 = 1, 0 XNOR 0 = 0, 1 XNOR 0 =0)
You may have seen 《A Summer Day's dream》, a doujin Animation of Touhou Project. Things go like the anime, Suika activated her ability, and the feast will loop for infinite times. This really troubles Reimu: to not make her customers feel bored, she must prepare enough numbers of different Nogaku scenes. Reimu find that each time the same guest will seat on the same seat, and She just have to prepare a new scene for a specific mask distribution. Two distribution plans are considered different, if any guest wears different masks.
In order to save faiths for Shrine, Reimu have to calculate that to make guests not bored, how many different Nogaku scenes does Reimu and Kokoro have to prepare. Due to the number may be too large, Reimu only want to get the answer modules 1e9+7 . Reimu did never attend Terakoya, so she doesn't know how to calculate in module. So Reimu wishes you to help her figure out the answer, and she promises that after you succeed she will give you a balloon as a gift.
Input
First line one number T , the number of testcases; (T≤20) .
Next TT lines each contains two numbers, N and k(0<N,k≤1e6) .
Output
For each testcase output one line with a single number of scenes Reimu and Kokoro have to prepare, the answer modules 1e9+7 .
样例输入
2
3 1
4 2
样例输出
2
84
题目来源及题目链接
ACM-ICPC 2018 徐州赛区网络预赛
题意:n个人,2k种面具,面具编号从0到2k-1,n个人围成圈,每一个人选择一种面具。相邻的人拥有的面具 ~(i^j)必须为正数,取反为对k位数取反。
思路:环形染色问题
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
ll qpow(ll a,ll b,ll c)
{
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a%c;
a=a*a%c;
b>>=1;
}
return ans;
}
void solve()
{
ll n,k;
scanf("%lld%lld",&n,&k);
if(k==1)
{
puts("2");
return ;
}
if(n==1)
{
printf("%lld\n",qpow(2,k,mod));
return ;
}
ll m = qpow(2,k,mod);
m = (m-1+mod)%mod;
ll answer = qpow(m,n,mod);
if(n%2==0)
answer=(answer + m)%mod;
else
answer=(answer-m+mod)%mod;
if(n>2&&n%2==1)
{
answer = (answer + qpow(2,k,mod)) %mod;
}
printf("%lld\n",answer);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
B.BE, GE or NE
In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named "Sena" are playing a video game. The game system of this video game is quite unique: in the process of playing this game, you need to constantly face the choice, each time you choose the game will provide 1-3 options, the player can only choose one of them. Each option has an effect on a "score" parameter in the game. Some options will increase the score, some options will reduce the score, and some options will change the score to a value multiplied by -1 .
That is, if there are three options in a selection, the score will be increased by 1, decreased by 1, or multiplied by -1. The score before the selection is 8. Then selecting option 1 will make the score become 9, and selecting option 2 will make the score 7 and select option 3 to make the score -8. Note that the score has an upper limit of 100 and a lower limit of -100. If the score is 99 at this time, an option that makes the score +2 is selected. After that, the score will change to 100 and vice versa .
After all the choices have been made, the score will affect the ending of the game. If the score is greater than or equal to a certain value kk, it will enter a good ending; if it is less than or equal to a certain value ll, it will enter the bad ending; if both conditions are not satisfied, it will enter the normal ending. Now, Koutarou and Sena want to play the good endings and the bad endings respectively. They refused to give up each other and finally decided to use the "one person to make a choice" way to play the game, Koutarou first choose. Now assume that they all know the initial score, the impact of each option, and the kk, ll values, and decide to choose in the way that works best for them. (That is, they will try their best to play the ending they want. If it's impossible, they would rather normal ending than the ending their rival wants.)
Koutarou and Sena are playing very happy, but I believe you have seen through the final ending. Now give you the initial score, the kk value, the ll value, and the effect of each option on the score. Can you answer the final ending of the game?
Input
The first line contains four integers n,m,k,ln,m,k,l(1≤n≤1000,−100≤m≤100 ,−100≤l<k≤100), represents the number of choices, the initial score, the minimum score required to enter a good ending, and the highest score required to enter a bad ending, respectively.
Each of the next nn lines contains three integers a,b,c(a≥0 , b≥0 ,c=0 or c=1),indicates the options that appear in this selection,in which a=0a=0 means there is no option to increase the score in this selection, a>0 means there is an option in this selection to increase the score by aa ; b=0 means there is no option to decrease the score in this selection, b>0 means there is an option in this selection to decrease the score by bb; c=0 means there is no option to multiply the score by −1 in this selection , c=1 means there is exactly an option in this selection to multiply the score by -1. It is guaranteed that a,b,c are not equal to 0 at the same time.
Output
One line contains the final ending of the game. If it will enter a good ending,print "Good Ending"(without quotes); if it will enter a bad ending,print "Bad Ending"(without quotes);otherwise print "Normal Ending"(without quotes).
样例输入1
3 -8 5 -5
3 1 1
2 0 1
0 2 1
样例输出1
Good Ending
样例输入2
3 0 10 3
0 0 1
0 10 1
0 2 1
样例输出2
Bad Ending
题目来源及题目链接
ACM-ICPC 2018 徐州赛区网络预赛
队友写的
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m,k,l,flag;
int a[1005],b[1005],c[1005];
int dp[2][1005][105];
int getsum(int d,int x)
{
if(d==0)
return -x;
else
return x;
}
int dfs(int d,int len,int x)
{
if(len==n+1)
return getsum(d,x);
if(dp[d][len][x]!=1000)
return dp[d][len][x];
int mm,sum,h;
if(len%2==1)
{
mm=-105;
if(a[len])
{
sum=getsum(d,x)+a[len];
if(sum>100)
sum=100;
if(sum<0)
h=dfs(0,len+1,-sum);
else
h=dfs(1,len+1,sum);
mm=max(mm,h);
}
if(b[len])
{
sum=getsum(d,x)-b[len];
if(sum<-100)
sum=-100;
if(sum<0)
h=dfs(0,len+1,-sum);
else
h=dfs(1,len+1,sum);
mm=max(mm,h);
}
if(c[len])
{
sum=getsum(d,x);
sum=-sum;
if(sum<0)
h=dfs(0,len+1,-sum);
else
h=dfs(1,len+1,sum);
mm=max(mm,h);
}
}
else
{
mm=105;
if(a[len])
{
sum=getsum(d,x)+a[len];
if(sum>100)
sum=100;
if(sum<0)
h=dfs(0,len+1,-sum);
else
h=dfs(1,len+1,sum);
mm=min(mm,h);
}
if(b[len])
{
sum=getsum(d,x)-b[len];
if(sum<-100)
sum=-100;
if(sum<0)
h=dfs(0,len+1,-sum);
else
h=dfs(1,len+1,sum);
mm=min(mm,h);
}
if(c[len])
{
sum=getsum(d,x);
sum=-sum;
if(sum<0)
h=dfs(0,len+1,-sum);
else
h=dfs(1,len+1,sum);
mm=min(mm,h);
}
}
dp[d][len][x]=mm;
return dp[d][len][x];
}
int main()
{
int i,j,ans;
scanf("%d%d%d%d",&n,&m,&k,&l);
for(i=1; i<=n; i++)
for(j=0; j<105; j++)
dp[0][i][j]=dp[1][i][j]=1000;
for(i=1; i<=n; i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]);
if(m>=0)
ans=dfs(1,1,m);
else
ans=dfs(0,1,-m);
if(ans>=k)
printf("Good Ending\n");
else if(k>ans&&ans>l)
printf("Normal Ending\n");
else if(ans<=l)
printf("Bad Ending\n");
return 0;
}
F.Features Track
Morgana is learning computer vision, and he likes cats, too. One day he wants to find the cat movement from a cat video. To do this, he extracts cat features in each frame. A cat feature is a two-dimension vector <x, y>. If xi= xj and yi = yj, then <xi, yi> <xj, yj> are same features.
So if cat features are moving, we can think the cat is moving. If feature <a,b> is appeared in continuous frames, it will form features movement. For example, feature <a,b> is appeared in frame 2,3,4,7,8, then it forms two features movement 2−3−4 and 7−8 .
Now given the features in each frames, the number of features may be different, Morgana wants to find the longest features movement.
Input
First line contains one integer T(1≤T≤10) , giving the test cases.
Then the first line of each cases contains one integer n (number of frames),
In The next nn lines, each line contains one integer ki ( the number of features) and 2ki intergers describe ki features in ith frame.(The first two integers describe the first feature, the 3rd and 4th integer describe the second feature, and so on).
In each test case the sum number of features N will satisfy N≤100000 .
Output
For each cases, output one line with one integers represents the longest length of features movement.
样例输入
1
8
2 1 1 2 2
2 1 1 1 4
2 1 1 2 2
2 2 2 1 4
0
0
1 1 1
1 1 1
样例输出
3
题目来源
ACM-ICPC 2018 徐州赛区网络预赛
题目大意:每次给出若干个点,输出连续出现最多次点的出现个数。
题目思路,stl map暴力
G.Trace
There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xx , yy ) means the wave is a rectangle whose vertexes are ( 0 , 0 ), ( x , 0 ), ( 0 , y ), ( x , y ). Every time the wave will wash out the trace of former wave in its range and remain its own trace of ( x , 0 ) -> ( x , y ) and ( 0 , y ) -> ( x , y ). Now the toad on the coast wants to know the total length of trace on the coast after n waves. It's guaranteed that a wave will not cover the other completely.
Input
The first line is the number of waves n(n≤50000).
The next nn lines,each contains two numbers xx yy ,( 0 < x , y≤10000000 ),the i-th line means the ii-th second there comes a wave of ( x , y ), it's guaranteed that when 1≤i , j ≤n ,xi≤xj and yi≤yj don't set up at the same time.
Output
An Integer stands for the answer.
Hint:
As for the sample input, the answer is 3+3+1+1+1+1=10
样例输入
3
1 4
4 1
3 3
样例输出
10
题目来源及链接
ACM-ICPC 2018 徐州赛区网络预赛
队友过的
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e6+5;
int num[maxn],c[maxn];
struct node
{
int index;
int x,y;
} e[maxn];
struct tree
{
int l,r;
int mmax;
} t[5*maxn];
void build(int i,int l,int r)
{
t[i].l=l,t[i].r=r,t[i].mmax=0;
if(l==r)
{
c[l]=i;
return ;
}
int mid=(l+r)/2;
build(2*i,l,mid);
build(2*i+1,mid+1,r);
}
void update(int i)
{
if(i==1)
return ;
int y=i/2;
t[y].mmax=max(t[2*y].mmax,t[2*y+1].mmax);
update(y);
}
int fd(int i,int l,int r)
{
if(t[i].l==l&&t[i].r==r)
return t[i].mmax;
int mid=(t[i].l+t[i].r)/2;
if(r<=mid)
return fd(2*i,l,r);
else if(l>mid)
return fd(2*i+1,l,r);
else
return max(fd(2*i,l,mid),fd(2*i+1,mid+1,r));
}
bool cmp3(node a,node b)
{
if(a.x!=b.x)
return a.x>b.x;
else
return a.index>b.index;
}
bool cmp4(node a,node b)
{
if(a.y!=b.y)
return a.y>b.y;
else
return a.index>b.index;
}
int main()
{
int i,j,k,n,h,x,y,sum;
long long ans=0;
scanf("%d",&n);
for(i=1; i<=n; i++)
{
scanf("%d%d",&x,&y);
e[i].x=x;
e[i].y=y;
e[i].index=i;
}
sort(e+1,e+n+1,cmp3);
build(1,1,n);
for(i=1; i<=n; i++)
{
j=e[i].index;
k=fd(1,j,n);
if(k>=e[i].y)
sum=0;
else
sum=e[i].y-k;
ans+=sum;
t[c[j]].mmax=e[i].y;
update(c[j]);
}
sort(e+1,e+n+1,cmp4);
build(1,1,n);
for(i=1; i<=n; i++)
{
j=e[i].index;
k=fd(1,j,n);
if(k>=e[i].x)
sum=0;
else
sum=e[i].x-k;
ans+=sum;
t[c[j]].mmax=e[i].x;
update(c[j]);
}
printf("%lld\n",ans);
return 0;
}
H.Ryuji doesn't want to study
Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i]a[i].
Unfortunately, the longer he learns, the fewer he gets.
That means, if he reads books from ll to rr, he will get a[l]×L+a[l+1]×(L−1)+⋯+a[r−1]×2+a[r] (L is the length of [ l, r ] that equals to r−l+1).
Now Ryuji has qq questions, you should answer him:
- If the question type is 1, you should answer how much knowledge he will get after he reads books [ l, r ].
- If the question type is 2, Ryuji will change the ith book's knowledge to a new value.
Input
First line contains two integers n and q (n,q≤100000).
The next line contains n integers represent a[i] (a[i]≤1e9) .
Then in next qq line each line contains three integers aa, bb, cc, if a = 1, it means question type is 1, and b, ccrepresents [ l , r ]. if a=2 , it means question type is 2 , and b, c means Ryuji changes the bth book' knowledge to c
Output
For each question, output one line with one integer represent the answer.
样例输入
5 3
1 2 3 4 5
1 1 3
2 5 0
1 4 5
样例输出
10
8
题目来源
ACM-ICPC 2018 徐州赛区网络预赛
题目大意:给一个序列,两种操作,区间求和(用上面加黑的公式),单点更新。
思路:开两棵线段树,一个颗存区间和,一个存 a1n , a2(n-1),a3(n-2)...an1 的和。
查询[l,r]的时候时候查询得到ans1,ans2。答案为ans2 - (n-r)*ans1。
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 100050;
struct node
{
int l,r;
ll sum;
} T[maxn*4],T2[maxn*4];
ll ans=0,a[maxn],b[maxn];
void build(int v,int l,int r)
{
T[v].l=l,T[v].r=r;
if(l==r)
{
T[v].sum=a[l];
return ;
}
int mid = (l+r)>>1;
build(v<<1,l,mid);
build(v<<1|1,mid+1,r);
T[v].sum = T[v<<1].sum+T[v<<1|1].sum;
}
void build2(int v,int l,int r)
{
T2[v].l=l,T2[v].r=r;
if(l==r)
{
T2[v].sum=b[l];
return ;
}
int mid = (l+r)>>1;
build2(v<<1,l,mid);
build2(v<<1|1,mid+1,r);
T2[v].sum = T2[v<<1].sum+T2[v<<1|1].sum;
}
void add(int v,int lie,ll value)
{
if(T[v].l==T[v].r)
{
T[v].sum = value;
return ;
}
int mid=(T[v].l+T[v].r)>>1;
if(lie<=mid)
add(v<<1,lie,value);
else
add(v<<1|1,lie,value);
T[v].sum = T[v<<1].sum+T[v<<1|1].sum;
}
void add2(int v,int lie,ll value)
{
if(T2[v].l==T2[v].r)
{
T2[v].sum = value;
return ;
}
int mid=(T2[v].l+T2[v].r)>>1;
if(lie<=mid)
add2(v<<1,lie,value);
else
add2(v<<1|1,lie,value);
T2[v].sum = T2[v<<1].sum+T2[v<<1|1].sum;
}
void query(int v,int l,int r)
{
if(T[v].l==l&&T[v].r==r)
{
ans += T[v].sum;
return ;
}
int mid=(T[v].l+T[v].r)>>1;
if(r<=mid)
{
query(v<<1,l,r);
}
else
{
if(l>mid)
{
query(v<<1|1,l,r);
}
else
{
query(v<<1,l,mid);
query(v<<1|1,mid+1,r);
}
}
}
void query2(int v,int l,int r)
{
if(T2[v].l==l&&T2[v].r==r)
{
ans += T2[v].sum;
return ;
}
int mid=(T2[v].l+T2[v].r)>>1;
if(r<=mid)
{
query2(v<<1,l,r);
}
else
{
if(l>mid)
{
query2(v<<1|1,l,r);
}
else
{
query2(v<<1,l,mid);
query2(v<<1|1,mid+1,r);
}
}
}
int main()
{
int n,q,op,x,y;
scanf("%d%d",&n,&q);
for(int i=1; i<=n; i++)
{
scanf("%lld",&a[i]);b[i]=a[i]*(n-i+1);
}
build(1,1,n);
build2(1,1,n);
while(q--)
{
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
ans=0;
query(1,x,y);
ll temp = ans;
ans=0;
query2(1,x,y);
printf("%lld\n",ans - (n-y)*temp);
}
else
{
add(1,x,y);
add2(1,x,1LL*y*(n-x+1));
}
}
return 0;
}
I.Characters with Hash
Mur loves hash algorithm, and he sometimes encrypt another one's name, and call him with that encrypted value. For instance, he calls Kimura KMR, and calls Suzuki YJSNPI. One day he read a book about SHA-256256 , which can transit a string into just 256 bits. Mur thought that is really cool, and he came up with a new algorithm to do the similar work. The algorithm works this way: first we choose a single letter L as the seed, and for the input(you can regard the input as a string ss, s[i] represents the iith character in the string) we calculates the value(|(int) L - s[i]|), and write down the number(keeping leading zero. The length of each answer equals to 2because the string only contains letters and numbers). Numbers writes from left to right, finally transfer all digits into a single integer(without leading zero(ss)). For instance, if we choose 'z' as the seed, the string "oMl" becomes "11 45 14".
It's easy to find out that the algorithm cannot transfer any input string into the same length. Though in despair, Mur still wants to know the length of the answer the algorithm produces. Due to the silliness of Mur, he can even not figure out this, so you are assigned with the work to calculate the answer.
Input
First line a integer T , the number of test cases (T≤10).
For each test case:
First line contains a integer N and a character z, (N≤1000000).
Second line contains a string with length NN . Problem makes sure that all characters referred in the problem are only letters.
Output
A single number which gives the answer.
样例输入
2
3 z
oMl
6 Y
YJSNPI
样例输出
6
10
题目来源
ACM-ICPC 2018 徐州赛区网络预赛
题目大意:给出每次一个长度为n的字符串,再给出一个特征字符,再将它与每个字符相减得到的值取绝对值,保留两位可含有前导0的数字,再将所有数字拼起来去除前导0,问最后有几位。
签到题,特判下最后一位都剩就好。
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
char ttr[1000005];
vector<int>E;
void solve()
{
E.clear();
int n;
char str[3];
scanf("%d%s",&n,str);
scanf("%s",ttr);
for(int i=0; i<n; i++)
{
//printf("%d ",ttr[i]-str[0]);
E.push_back(abs(ttr[i]-str[0]));
}
int answer = E.size()*2;
for(int i=0; i<E.size(); i++)
{
if(E[i]==0)
answer-=2;
else
{
if(E[i]<10)
{
answer--;
}
break;
}
}
if(answer==0)answer = 1;
printf("%d\n",answer);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
J. Maze Designer
After the long vacation, the maze designer master has to do his job. A tour company gives him a map which is a rectangle. The map consists of N \times MN×M little squares. That is to say, the height of the rectangle is NN and the width of the rectangle is MM. The master knows exactly how the maze is going to use. The tour company will put a couple in two different squares in the maze and make them seek each other. Of course,the master will not make them find each other easily. The only thing the master does is building some wall between some little squares. He knows in that way, wherever the couple is put, there is only one path between them. It is not a difficult thing for him, but he is a considerate man. He also knows that the cost of building every wall between two adjacent squares is different(Nobody knows the reason). As a result, he designs the maze to make the tour company spend the least money to build it.
Now, here's your part. The tour company knows you're the apprentice of the master, so they give you a task. you're given QQ qustions which contain the information of where the couple will be put. You need to figure out the length of the shortest path between them.
However,the master doesn't tell you how he designs the maze, but he believes that you, the best student of himself, know the way. So he goes on vacation again.
Input
The first line of the input contains two integers NN and MM (1≤N,M≤500), giving the number of rows and columns of the maze.
The next N×M lines of the input give the information of every little square in the maze, and their coordinates are in order of (1,1) , (1,2) ⋯ (1,M)(1,M) , (2,1) ,(2,2) ,⋯ , (2,M) , ⋯ ,(N,M)
Each line contains two characters DD and RR and two integers a , b (0≤a,b≤2000000000 ), aa is the cost of building the wall between it and its lower adjacent square, and bb is the cost of building the wall between it and its right adjacent square. If the side is boundary, the lacking path will be replaced with X 0.
The next line contains an integer Q (1≤Q≤100000 ), which represents the number of questions.
The next Q lines gives four integers, x1,y1, x2, y2 ( 1≤x1 , x2≤N , 1≤y1 , y2≤M ), which represent two squares and their coordinate are (x1 , y1) and (x2 , y2).
(x,y) means row xx and column yy.
It is guaranteed that there is only one kind of maze.
Output
For each question, output one line with one integer which represents the length of the shortest path between two given squares.
样例输入
3 3
D 1 R 9
D 7 R 8
D 4 X 0
D 2 R 6
D 12 R 5
D 3 X 0
X 0 R 10
X 0 R 11
X 0 X 0
3
1 1 3 3
1 2 3 2
2 2 3 1
样例输出
4
2
2
题目来源
ACM-ICPC 2018 徐州赛区网络预赛
题目大意:给一个矩阵,矩阵格与格之间可以花费一定费用建一堵墙,题目要求使用最少的花费使得每个矩阵格到其他矩阵格只有一条路径,然后询问某两个格的路径长度。
题目思路,求最大生成树,然后预处理LCA求树上任意两点距离。
x到y的距离 = dist[x] + dist[y] - 2 dist[LCA(x,y)],dist为根到节点的距离。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 500*500 +50;
int level[maxn];
int st[maxn][25];
int first[maxn];
int dist[maxn];
struct Edge
{
int to,w,next;
}edge[maxn*4];
int sign;
void init() {
memset(first, -1, sizeof(first));
sign = 0;
}
void add_edge(int u, int v, int w) {
edge[sign].to = v;
edge[sign].w = w;
edge[sign].next = first[u];
first[u] = sign++;
}
struct node
{
int x,y,w;
}edge1[maxn*4];
int etot = 0;
bool cmp(node a,node b)
{
return a.w>b.w;
}
void dfs(int now, int father) {
level[now] = level[father] + 1;
st[now][0] = father;
for(int i = 1; (1 << i) <= level[now]; i ++ ) {
st[now][i] = st[ st[now][i - 1] ][i - 1];
}
for(int i = first[now]; ~i; i = edge[i].next) {
int to = edge[i].to, w = edge[i].w;
if(to == father) {
continue;
}
dist[to] = dist[now] + 1;
dfs(to, now);
}
}
int LCA(int x, int y) {
if(level[x] > level[y]) {
swap(x, y);
}
for(int i = 20; i >= 0; i -- ) {
if(level[x] + (1 << i) <= level[y]) {
y = st[y][i];
}
}
if(x == y) {
return x;
}
for(int i = 20; i >= 0; i -- ) {
if(st[x][i] == st[y][i]) {
continue;
} else {
x = st[x][i], y = st[y][i];
}
}
return st[x][0];
}
int father[maxn];
void make_set(int n)
{
for(int i=0; i<=n; i++)father[i]=i;
}
int Find(int x)
{
int p,tmp;
p = x;
while(x != father[x])
x = father[x];
while(p!=x)
{
tmp = father[p];
father[p] = x;
p = tmp;
}
return x;
}
int main()
{
int n,m,num,t,q;
char str[5];
scanf("%d%d",&n,&m);
for(int i=1; i<=n*m; i++)
{
t = 2;
while(t--)
{
scanf("%s%d",str,&num);
if(str[0]=='D')
{
edge1[etot].x = i;
edge1[etot].y = i+m;
edge1[etot++].w = num;
}
else if(str[0]=='R')
{
edge1[etot].x = i;
edge1[etot].y = i+1;
edge1[etot++].w = num;
}
}
}
sort(edge1,edge1+etot,cmp);
make_set(n*m);
init();
int cnt = 0;
for(int i=0;i<etot;i++)
{
int x = Find(edge1[i].x),y = Find(edge1[i].y);
if(x!=y)
{
cnt++;
father[x]=y;
add_edge(edge1[i].x,edge1[i].y,1);
add_edge(edge1[i].y,edge1[i].x,1);
}
}
dfs(1,-1);
scanf("%d",&q);
while(q--)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int a =(x1-1)*m+y1;
int b =(x2-1)*m+y2;
printf("%d\n",dist[a]+dist[b]-2*dist[LCA(a,b)]);
}
return 0;
}