暑假训练day3

Bombing

 It’s a cruel war which killed millions of people and ruined series of cities. In order to stop it, let’s bomb the opponent’s base.
It seems not to be a hard work in circumstances of street battles, however, you’ll be encountered a much more difficult instance: recounting exploits of the military. In the bombing action, the commander will dispatch a group of bombers with weapons having the huge destructive power to destroy all the targets in a line. Thanks to the outstanding work of our spy, the positions of all opponents’ bases had been detected and marked on the map, consequently, the bombing plan will be sent to you.
Specifically, the map is expressed as a 2D-plane with some positions of enemy’s bases marked on. The bombers are dispatched orderly and each of them will bomb a vertical or horizontal line on the map. Then your commanded wants you to report that how many bases will be destroyed by each bomber. Notice that a ruined base will not be taken into account when calculating the exploits of later bombers.

Input
Multiple test cases and each test cases starts with two non-negative integer N (N<=100,000) and M (M<=100,000) denoting the number of target bases and the number of scheduled bombers respectively. In the following N line, there is a pair of integers x and y separated by single space indicating the coordinate of position of each opponent’s base. The following M lines describe the bombers, each of them contains two integers c and d where c is 0 or 1 and d is an integer with absolute value no more than 109, if c = 0, then this bomber will bomb the line x = d, otherwise y = d. The input will end when N = M = 0 and the number of test cases is no more than 50.
Output
For each test case, output M lines, the ith line contains a single integer denoting the number of bases that were destroyed by the corresponding bomber in the input. Output a blank line after each test case.
Sample Input

3 2
1 2
1 3
2 3
0 1
1 3
0 0

Sample Output

2
1

题意:给你n个敌人的坐标,再给你m个炸弹和爆炸方向,每个炸弹可以炸横排或竖排的敌人,问你每个炸弹能炸死多少个人。

题解:map+multiset模拟即可

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>
#include<cstring>

using namespace std;


int main() {
    int n, m, x, y;
    ios::sync_with_stdio(false);
    while (cin >> n >> m && n && m) {
        map<int, multiset<int> > mx;
        map<int, multiset<int> > my;
        for (int i = 1; i <= n; i++) {
            cin >> x >> y;
            mx[x].insert(y);
            my[y].insert(x);
        }
        multiset<int>::iterator it;
        for (int i = 1; i <= m; i++) {
            cin >> x >> y;
            if (x == 0) {
                cout << mx[y].size() << endl;
                for (it = mx[y].begin(); it != mx[y].end(); it++) {
                    my[*it].erase(my[*it].find(y));
                }
                mx[y].clear();
            } else {
                cout << my[y].size() << endl;
                for (it = my[y].begin(); it != my[y].end(); it++) {
                    mx[*it].erase(mx[*it].find(y));
                }
                my[y].clear();
            }
        }
        cout << endl;
    }
    return 0;
}

Constructing the Array

You are given an array a of length n consisting of zeros. You perform n actions with this array: during the i

-th action, the following sequence of operations appears:

Choose the maximum by length subarray (continuous subsegment) consisting only of zeros, among all such segments choose the leftmost one;
Let this segment be [l;r]

. If r−l+1 is odd (not divisible by 2) then assign (set) a[l+r2]:=i (where i is the number of the current action), otherwise (if r−l+1 is even) assign (set) a[l+r−12]:=i

.

Consider the array a
of length 5 (initially a=[0,0,0,0,0]

). Then it changes as follows:

Firstly, we choose the segment [1;5]

and assign a[3]:=1, so a becomes [0,0,1,0,0]
;
then we choose the segment [1;2]
and assign a[1]:=2, so a becomes [2,0,1,0,0]
;
then we choose the segment [4;5]
and assign a[4]:=3, so a becomes [2,0,1,3,0]
;
then we choose the segment [2;2]
and assign a[2]:=4, so a becomes [2,4,1,3,0]
;
and at last we choose the segment [5;5]
and assign a[5]:=5, so a becomes [2,4,1,3,5]

.

Your task is to find the array a
of length n after performing all n

actions. Note that the answer exists and unique.

You have to answer t

independent test cases.

Input

The first line of the input contains one integer t

(1≤t≤104) — the number of test cases. Then t

test cases follow.

The only line of the test case contains one integer n
(1≤n≤2⋅105) — the length of a

.

It is guaranteed that the sum of n
over all test cases does not exceed 2⋅105 (∑n≤2⋅105

).

Output

For each test case, print the answer — the array a

of length n after performing n

actions described in the problem statement. Note that the answer exists and unique.

Example
Input

6
1
2
3
4
5
6

Output

1 
1 2 
2 1 3 
3 1 2 4 
2 4 1 3 5 
3 4 1 5 2 6 

题意:模拟二分插入1-n的数字

题解:模拟二分即可

include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>
#include<cstring>

using namespace std;
const int N = 2e5 + 5;

pair<int, int> a[N];

void B_S(int l, int r) {
    if (l <= r) {
        int mid = (l + r) >> 1;
        a[mid].first = l - r - 1;
        B_S(l, mid - 1);
        B_S(mid + 1, r);
    }
}

int main(void) {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        B_S(1, n);
        for (int i = 1; i <= n; i++) a[i].second = i;
        sort(a + 1, a + n + 1);
        int ans[N] = {0};
        for (int i = 1; i <= n; i++) ans[a[i].second] = i;
        for (int i = 1; i <= n; i++) cout << ans[i] << " ";
        cout << endl;
    }
}

士兵队列训练问题

 某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。

Input
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
Output
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
Sample Input

2
20
40

Sample Output

1 7 19
1 19 37

题解:vector 模拟即可

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>

using namespace std;

int main(void) {
    int n, t;
    bool flag1;
    while (cin >> t) {
        while (t--) {
            cin >> n;
            vector<int> q;
            for (int i = 0; i < n; i++)
                q.push_back(i + 1);
            flag1 = false;
            int tmp;
            while (q.size() > 3) {
                if (flag1 == false) {
                    flag1 = true;
                    tmp = 1;
                } else {
                    flag1 = false;
                    tmp = 2;
                }
                for (int i = tmp; i < q.size(); i += tmp) {
                    q.erase(q.begin() + i);
                }
            }
            for (int i = 0; i < q.size() - 1; i++)
                cout << q[i] << " ";
            cout << q[q.size()-1] << endl;
        }
    }
    return 0;
}

Anagram

You are to write a program that has to generate all possible words from a given set of letters.
Example: Given the word "abc", your program should - by exploring all different combination of the three letters - output the words "abc", "acb", "bac", "bca", "cab" and "cba".
In the word taken from the input file, some letters may appear more than once. For a given word, your program should not produce the same word more than once, and the words should be output in alphabetically ascending order.

Input
The input consists of several words. The first line contains a number giving the number of words to follow. Each following line contains one word. A word consists of uppercase or lowercase letters from A to Z. Uppercase and lowercase letters are to be considered different. The length of each word is less than 13.
Output
For each word in the input, the output should contain all different words that can be generated with the letters of the given word. The words generated from the same input word should be output in alphabetically ascending order. An upper case letter goes before the corresponding lower case letter.
Sample Input

3
aAb
abc
acba

Sample Output

Aab
Aba
aAb
abA
bAa
baA
abc
acb
bac
bca
cab
cba
aabc
aacb
abac
abca
acab
acba
baac
baca
bcaa
caab
caba
cbaa

Hint
An upper case letter goes before the corresponding lower case letter.
So the right order of letters is ‘A’<‘a’<‘B’<‘b’<…<‘Z’<‘z’.

题解 : 字母全排列

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>

using namespace std;

bool cmp(char a, char b) {
    if ((a >= 'a' && a <= 'z') && (b >= 'a' && b <= 'z'))
        return a < b;
    if ((a >= 'A' && a <= 'Z') && (b >= 'A' && b <= 'Z'))
        return a < b;
    if ((a >= 'a' && a <= 'z') && (b >= 'A' && b <= 'Z'))
        return a < b + 32;
    if ((a >= 'A' && a <= 'Z') && (b >= 'a' && b <= 'z'))
        return a + 32 <= b;
}

int main(void) {
    int t;
    string a;
    cin >> t;
    while (t--) {
        cin >> a;
        sort(a.begin(), a.end(), cmp);
        cout << a << endl;
        while (next_permutation(a.begin(), a.end(), cmp))
        cout << a << endl;
    }
    return 0;
}

Fence Repair

Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li). FJ is ignoring the "kerf", the extra length lost to sawdust when a sawcut is made; you should ignore it, too.

FJ sadly realizes that he doesn't own a saw with which to cut the wood, so he mosies over to Farmer Don's Farm with this long board and politely asks if he may borrow a saw.

Farmer Don, a closet capitalist, doesn't lend FJ a saw but instead offers to charge Farmer John for each of the N-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.

Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create the N planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.

Input
Line 1: One integer N, the number of planks
Lines 2…N+1: Each line contains a single integer describing the length of a needed plank
Output
Line 1: One integer: the minimum amount of money he must spend to make N-1 cuts
Sample Input

3
8
5
8

Sample Output

34

Hint
He wants to cut a board of length 21 into pieces of lengths 8, 5, and 8.
The original board measures 8+5+8=21. The first cut will cost 21, and should be used to cut the board into pieces measuring 13 and 8. The second cut will cost 13, and should be used to cut the 13 into 8 and 5. This would cost 21+13=34. If the 21 was cut into 16 and 5 instead, the second cut would cost 16 for a total of 37 (which is more than 34).

题意:有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度(锯之前的长度)

给定各个要求的小木板的长度,及小木板的个数n,求最小费用

题解:用优先队列来组

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>

using namespace std;

int main() {
    long long ans = 0;
    priority_queue<long long, vector<long long>, greater<long long>> p;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int l;
        cin >> l;
        p.push(l);
    }
    while (p.size() > 1) {
        long long a = p.top();
        p.pop();
        long long b = p.top();
        p.pop();
        p.push(a + b);
        ans += a + b;
    }
    cout << ans << endl;
}

Black Box

Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empty and i equals 0. This Black Box processes a sequence of commands (transactions). There are two types of transactions:

ADD (x): put element x into Black Box;
GET: increase i by 1 and give an i-minimum out of all integers containing in the Black Box. Keep in mind that i-minimum is a number located at i-th place after Black Box elements sorting by non- descending.

Let us examine a possible sequence of 11 transactions:

Example 1


N Transaction i Black Box contents after transaction Answer 

      (elements are arranged by non-descending)   

1 ADD(3)      0 3   

2 GET         1 3                                    3 

3 ADD(1)      1 1, 3   

4 GET         2 1, 3                                 3 

5 ADD(-4)     2 -4, 1, 3   

6 ADD(2)      2 -4, 1, 2, 3   

7 ADD(8)      2 -4, 1, 2, 3, 8   

8 ADD(-1000)  2 -1000, -4, 1, 2, 3, 8   

9 GET         3 -1000, -4, 1, 2, 3, 8                1 

10 GET        4 -1000, -4, 1, 2, 3, 8                2 

11 ADD(2)     4 -1000, -4, 1, 2, 2, 3, 8   


It is required to work out an efficient algorithm which treats a given sequence of transactions. The maximum number of ADD and GET transactions: 30000 of each type.


Let us describe the sequence of transactions by two integer arrays:


1. A(1), A(2), ..., A(M): a sequence of elements which are being included into Black Box. A values are integers not exceeding 2 000 000 000 by their absolute value, M <= 30000. For the Example we have A=(3, 1, -4, 2, 8, -1000, 2).

2. u(1), u(2), ..., u(N): a sequence setting a number of elements which are being included into Black Box at the moment of first, second, ... and N-transaction GET. For the Example we have u=(1, 2, 6, 6).

The Black Box algorithm supposes that natural number sequence u(1), u(2), ..., u(N) is sorted in non-descending order, N <= M and for each p (1 <= p <= N) an inequality p <= u(p) <= M is valid. It follows from the fact that for the p-element of our u sequence we perform a GET transaction giving p-minimum number from our A(1), A(2), ..., A(u(p)) sequence.

Input
Input contains (in given order): M, N, A(1), A(2), …, A(M), u(1), u(2), …, u(N). All numbers are divided by spaces and (or) carriage return characters.
Output
Write to the output Black Box answers sequence for a given sequence of transactions, one number each line.
Sample Input

7 4
3 1 -4 2 8 -1000 2
1 2 6 6

Sample Output

3
3
1
2

题意:给你n个插入的数和m次查询,每次查询输入一个数表示在第几次插入操作以后查询(是第几次查询就输出第几个小的数)

题解:对顶堆来进行动态维护

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>
#include<cstring>

using namespace std;

int main(void) {
    int n, m;
    while (cin >> n >> m) {
        int a[30010];
        int c = 0, t;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        priority_queue<int, vector<int>, less<int> > p;
        priority_queue<int, vector<int>, greater<int> > pg;
        for (int i = 0; i < m; i++) {
            int x;
            cin >> x;
            while (c < x) {
                pg.push(a[c]);
                c++;
            }
            while (!p.empty() && p.top() > pg.top()) {
                t = p.top();
                p.pop();
                p.push(pg.top());
                pg.pop();
                pg.push(t);
            }
            cout << pg.top() << endl;
            p.push(pg.top());
            pg.pop();
        }
    }
    return 0;
}

迷宫问题

定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};


它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

经典迷宫问题。。。。

#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<string>
#include<set>
#include<cmath>
#include<cstring>

using namespace std;


struct point {
    int x;
    int y;
};

queue<point> q;
int m[10][10];
int step[10][10];
bool vis[10][10];

int bfs() {
    memset(vis, false, sizeof(vis));
    step[0][0] = 0;
    point init;
    init.x = 0;
    init.y = 0;
    vis[0][0] = true;
    q.push(init);
    while (!q.empty()) {
        point head = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            point next = head;
            if (i == 0) next.x = head.x + 1;
            else if (i == 1) next.x = head.x - 1;
            else if (i == 2) next.y = head.y + 1;
            else if (i == 3) next.y = head.y - 1;
            if (next.x < 0 || next.x > 4 || next.y < 0 || next.y > 4 || (m[next.y][next.x] == 1))
                continue;
            if (!vis[next.y][next.x]) {
                q.push(next);
                step[next.y][next.x] = step[head.y][head.x] + 1;
                vis[next.y][next.x] = true;
            }
            if (next.x == 4 && next.y == 4) {
                return step[head.y][head.x];
            }
        }
    }
}

int main() {
    memset(m, 0, sizeof(m));
    memset(step, 0, sizeof(step));
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            cin >> m[i][j];
        }
    }
    bfs();
    int cnt = 0;
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (step[i][j] == cnt) {
                cout <<"("<<i <<", "<< j <<")" << endl;
                cnt++;
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值