第七周周赛——字典树 + 线段树 + 树状数组等等(去师大比赛前的最后一场) Mobile phones Interesting Array Wizards' Duel Babelfish

第七周周赛——字典树 + 线段树 + 树状数组等等(去师大比赛前的最后一场)

Mobile phones

Interesting Array

Wizards' Duel

Babelfish

题目分别出自:

poj1195,codeforces 482B,codeforces 591A。poj 2503,poj2442,codeforces 445B

A题:

A题题目链接

题目描写叙述:

TimeLimit:5000MS  MemoryLimit:65536K
64-bit integer IO format:%lld

Problem Description
Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The squares form an S * S matrix with the rows and columns numbered from 0 to S-1. Each square contains a base station. The number of active mobile phones inside a square can change because a phone is moved from a square to another or a phone is switched on or off. At times, each base station reports the change in the number of active phones to the main base station along with the row and the column of the matrix. 

Write a program, which receives these reports and answers queries about the current total number of active mobile phones in any rectangle-shaped area. 
Input
The input is read from standard input as integers and the answers to the queries are written to standard output as integers. The input is encoded as follows. Each input comes on a separate line, and consists of one instruction integer and a number of parameter integers according to the following table. 
第七周周赛——字典树 + 线段树 + 树状数组等等(去师大比赛前的最后一场)

Mobile phones

Interesting Array

Wizards' Duel

Babelfish

The values will always be in range, so there is no need to check them. In particular, if A is negative, it can be assumed that it will not reduce the square value below zero. The indexing starts at 0, e.g. for a table of size 4 * 4, we have 0 <= X <= 3 and 0 <= Y <= 3. 

Table size: 1 * 1 <= S * S <= 1024 * 1024 
Cell value V at any time: 0 <= V <= 32767 
Update amount: -32768 <= A <= 32767 
No of instructions in input: 3 <= U <= 60002 
Maximum number of phones in the whole table: M= 2^30 
Output
Your program should not answer anything to lines with an instruction other than 2. If the instruction is 2, then your program is expected to answer the query by writing the answer as a single line containing a single integer to standard output.
SampleInput
0 4
1 1 2 3
2 0 0 2 2 
1 1 1 2
1 1 2 -1
2 1 1 2 3 
3
SampleOutput
3
4

解析:

A题先晾着。树状数组这一块还没有进行系统的学习。

有兴趣的能够自己做做或者百度一下相关知识学一学。

B题:

B题题目链接

题目描写叙述:

Interesting Array

TimeLimit:1000MS  MemoryLimit:256MB
64-bit integer IO format:%I64d

Problem Description

We'll call an array of n non-negative integers a[1], a[2], ..., a[n] interesting, if it meets m constraints. The i-th of the mconstraints consists of three integers liriqi (1 ≤ li ≤ ri ≤ n) meaning that value 第七周周赛——字典树 + 线段树 + 树状数组等等(去师大比赛前的最后一场)

Mobile phones

Interesting Array

Wizards' Duel

Babelfish should be equal to qi.

Your task is to find any interesting array of n elements or state that such array doesn't exist.

Expression x&y means the bitwise AND of numbers x and y. In programming languages C++, Java and Python this operation is represented as "&", in Pascal — as "and".

Input

The first line contains two integers nm (1 ≤ n ≤ 1051 ≤ m ≤ 105) — the number of elements in the array and the number of limits.

Each of the next m lines contains three integers liriqi (1 ≤ li ≤ ri ≤ n0 ≤ qi < 230) describing the i-th limit.

Output

If the interesting array exists, in the first line print "YES" (without the quotes) and in the second line print n integersa[1], a[2], ..., a[n] (0 ≤ a[i] < 230) decribing the interesting array. If there are multiple answers, print any of them.

If the interesting array doesn't exist, print "NO" (without the quotes) in the single line.

SampleInput 1
3 1
1 3 3
SampleOutput 1
YES
3 3 3
SampleInput 2
3 2
1 3 3
1 3 2
SampleOutput 2
NO

题意:

给定n,m,分别表示数组a中元素的个数和"限制"的组数,接下来是m组限制,每组限制有三个数据。各自是l,r。p,表示要满

足条件数组a[l] & a[l+1] & ...a[r] = p,然后要求输出满足以上全部m组限制的数组a。假设有多组满足的话,输出随意一组就可以。

解析:

一開始拿到这道题的时候。看到区间问题。立即反应过来要用线段树。

但是想了非常久,依据自己掌握的知识,先要构建一棵线段树,但是题目中却是要输出这种一个数组,意思就是一開始并不提供构建线段树的条件(即数组元素),而是给你一些查询,让你

通过这些查询来输出一棵满足全部查询的树。然后我就纳闷了,去翻了翻当时的官方题解,发现思路很巧妙。题解的思路也就是

将这些查询转换成对应的条件。然后通过这些条件先预处理一棵通过这些条件不断更新后得到的一棵线段树,然后最后再通过这

棵线段树来推断这些条件是否一一成立,若当中有不成立的,说明得到的这棵线段树与已知的查询矛盾。则输出NO。反之则一一

输出线段树中存储的数据元素。即数组元素。

官方题解出处:点击打开链接

完整代码实现:

#include<cstdio>
#include<cstring>

const int MAX_BIT = 29;        //表示最大的位数(二进制位)
const int MAX_NUM = (int)1e5 + 10;
const int INF = (1 << 30) - 1;       //注意这里的无穷大的取值,不能随便取值
int l[MAX_NUM],r[MAX_NUM],q[MAX_NUM],a[MAX_NUM],sum[MAX_NUM],n,m;
int tree[MAX_NUM * 4];

//数组建立线段树,v为当前遍历到的节点的下标,根节点为1,l,r分别为线段树节点存储的区间的左值和右值
void build(int v,int l,int r){
    //遍历到了叶节点
    if(l == r){
        tree[v] = a[l];
        return;
    }

    int lson = v << 1,rson = lson + 1,mid = (l+r) >> 1;

    build(lson,l,mid);
    build(rson,mid+1,r);

    //节点存储的值为其左右孩子存储的值相与后的结果
    tree[v] = tree[lson] & tree[rson];
}
/**v,l,r表示当前遍历到的节点的下标以及存储的左右区间值
 **ql,qr表示待查询的区间
 */
int Query(int v, int l, int r, int ql, int qr) {
    if (r < ql || l > qr)  return INF;

    if (ql <= l && r <= qr)  return tree[v];

    int lson = v<<1, rson = lson+1, mid = (l+r)>>1;

    return Query(lson, l, mid, ql, qr) & Query(rson, mid+1, r, ql, qr);
}

void Init(){
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= m;++i){
        scanf("%d %d %d",&l[i],&r[i],&q[i]);
    }

    for(int i = 0;i <= MAX_BIT;++i){    //考虑q[i]的每一位,假设该位是1。那么数组a[l[i]] —— a[r[i]]相应位均要为1
        memset(sum,0,sizeof(sum));
        for(int j = 1;j <= m;++j){
            if((q[j] >> i) & 1){      
                ++sum[l[j]];
                --sum[r[j]+1];  //sum用来标记每次处理的区间
            }
        }
        for(int j = 1;j <= n;++j){
            sum[j] += sum[j-1];
            if(sum[j] > 0){     //表示处理到的这一位不为0
                a[j] |= 1 << i;
            }
        }
    }
    build(1,1,n);
}

void solve(){
    for(int i = 1;i <= m;++i){
        if(Query(1,1,n,l[i],r[i])!=q[i]){
            printf("NO
");
            return;
        }
    }
    printf("YES
");
    for(int i = 1;i <= n;++i){
        if(i-1){
            printf(" ");
        }
        printf("%d ",a[i]);
    }
    printf("
");
}
int main(){
    Init();
    solve();
    return 0;
}



这道题目是非常好的题目。感觉自己还不是非常懂,等到过段时间线段树这部分总结了之后一定要再来看看。

C题:

C题题目链接

题目描写叙述:

Wizards' Duel

TimeLimit:2000MS  MemoryLimit:256MB
64-bit integer IO format:%I64d

Problem Description

Harry Potter and He-Who-Must-Not-Be-Named engaged in a fight to the death once again. This time they are located at opposite ends of the corridor of length l. Two opponents simultaneously charge a deadly spell in the enemy. We know that the impulse of Harry's magic spell flies at a speed of p meters per second, and the impulse of You-Know-Who's magic spell flies at a speed of q meters per second.

The impulses are moving through the corridor toward each other, and at the time of the collision they turn round and fly back to those who cast them without changing their original speeds. Then, as soon as the impulse gets back to it's caster, the wizard reflects it and sends again towards the enemy, without changing the original speed of the impulse.

Since Harry has perfectly mastered the basics of magic, he knows that after the second collision both impulses will disappear, and a powerful explosion will occur exactly in the place of their collision. However, the young wizard isn't good at math, so he asks you to calculate the distance from his position to the place of the second meeting of the spell impulses, provided that the opponents do not change positions during the whole fight.

Input

The first line of the input contains a single integer l (1 ≤ l ≤ 1 000) — the length of the corridor where the fight takes place.

The second line contains integer p, the third line contains integer q (1 ≤ p, q ≤ 500) — the speeds of magical impulses for Harry Potter and He-Who-Must-Not-Be-Named, respectively.

Output

Print a single real number — the distance from the end of the corridor, where Harry is located, to the place of the second meeting of the spell impulses. Your answer will be considered correct if its absolute or relative error will not exceed10 - 4.

Namely: let's assume that your answer equals a, and the answer of the jury is b. The checker program will consider your answer correct if 第七周周赛——字典树 + 线段树 + 树状数组等等(去师大比赛前的最后一场)

Mobile phones

Interesting Array

Wizards' Duel

Babelfish.

SampleInput 1
100
50
50
SampleOutput 1
50
SampleInput 2
199
60
40
SampleOutput 2
119.4
Note

In the first sample the speeds of the impulses are equal, so both of their meetings occur exactly in the middle of the corridor.

题意:

Harry 和 He-Who-Must-Not-Be-Named 分别在走廊末端,各发射自己的impulse,当中Harry 的 impulse 速度为 p 米/s。He-Who-

Must-Not-Be-Named为 q米/s。

然后相遇之后各自回到它们的主人身边。再发射。再发射时的速度保持不变。问第二次相遇的时候。

Harry的impulse 离他的位置距离是多少。

解析:

因为第二次再发射的时候速度保持不变。因此相遇点仍然是第一次相遇的那个点。

因此得出一元一次方程(p+q)* t = l;

然后再p*t则是全部答案。

完整代码实现:

#include<cstdio>
int main(){
    int l,p,q;
    scanf("%d %d %d",&l,&p,&q);
    printf("%.6f
",(double)l/(p+q)*p);
}


D题:

D题题目链接

题目描写叙述:

Babelfish

TimeLimit:3000MS  MemoryLimit:65536K
64-bit integer IO format:%lld

Problem Description
You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language. Fortunately, you have a dictionary to help you understand them.
Input
Input consists of up to 100,000 dictionary entries, followed by a blank line, followed by a message of up to 100,000 words. Each dictionary entry is a line containing an English word, followed by a space and a foreign language word. No foreign word appears more than once in the dictionary. The message is a sequence of words in the foreign language, one word on each line. Each word in the input is a sequence of at most 10 lowercase letters.
Output
Output is the message translated to English, one word per line. Foreign words not in the dictionary should be translated as "eh".
SampleInput
dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay

atcay
ittenkay
oopslay
SampleOutput
cat
eh
loops
题意:

在词典中,给定一些翻译后的单词及翻译前的单词,然后空行隔开,再给定一些翻译前的单词。假设这些翻译前的单词存在词

典中,那么输出其翻译后的单词,否则的话,则输出字符串eh。

解析:

这道题因为数据量很大。词典中最多高达10^5组单词,并且查询次数也达到了10^5次方,因此暴力遍历的方法显然是不可行

的,因为这道题的时限比較宽松。因此用映射容器map也能过。注意空行的处理,在这里空行仅仅有一个' '字符。

完整代码实现:

#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<cstring>
#include<cstdio>
using namespace std;
map <string,string> mp;
int main(){
    char temp[50];
    string str,str1,str2;
    while(gets(temp) && strlen(temp)){
        for(int j = 0;;++j){
            if(temp[j]==' '){
                temp[j] = '