7.16,7.18练习题

Though Rujia Liu usually sets hard problems for contests (for example, regional contests like
Xi’an 2006, Beijing 2007 and Wuhan 2009, or UVa OJ contests like Rujia Liu’s Presents 1
and 2), he occasionally sets easy problem (for example, ‘the Coco-Cola Store’ in UVa OJ),
to encourage more people to solve his problems :D
Given an array, your task is to find the k-th occurrence (from left to right) of an integer v. To make the problem more difficult (and interesting!), you’ll have to answer m such queries.
Input There are several test cases. The first line of each test case contains two integers n, m (1 ≤ n,m ≤ 100,000), the number of elements in the array, and the number of queries. The next line contains n positive integers not larger than 1,000,000. Each of the following m lines contains two integer k and v (1 ≤ k ≤ n, 1 ≤ v ≤ 1,000,000). The input is terminated by end-of-file (EOF).
Output
For each query, print the 1-based location of the occurrence. If there is no such element, output ‘0’ instead.
Sample Input
8 4

1 3 2 2 4 3 2 1

1 3

2 4

3 2

4 2
Sample Output
2

0

7

0

题意:给你一组数,再给你要查的内容,让你查找该数第几次出现的位置

一开始直接暴力,但是没过,超时,这道题用vector容器其实很简单,只是我没想到

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7;
vector<int>p[maxn];
int main()
{
    int n,m,k,v,a,ans;
    while(cin>>n>>m)
    {
        for(int i=0;i<1000000;i++)
           p[i].clear();
        for(int i=1;i<=n;i++)
        {
            cin>>a;
            p[a].push_back(i);//记录位置
        }
        for(int i=0;i<m;i++)
        {
            cin>>k>>v;
            if(p[v].size()<k)
               ans=0;
            else
              ans=p[v][k-1];
            cout<<ans<<endl;
        }
    }
} 

Buy Low Sell High

You can perfectly predict the price of a certain stock for the next N days. You would like to profit on this knowledge, but only want to transact one share of stock per day. That is, each day you will either buy one share, sell one share, or do nothing. Initially you own zero shares, and you cannot sell shares when you don't own any. At the end of the N days you would like to again own zero shares, but want to have as much money as possible.

Input

Input begins with an integer N (2 ≤ N ≤ 3·105), the number of days.

Following this is a line with exactly N integers p1, p2, ..., pN (1 ≤ pi ≤ 106). The price of one share of stock on the i-th day is given by pi.

Output

Print the maximum amount of money you can end up with at the end of N days.

Examples

Input
9
10 5 4 7 9 12 6 2 10
Output
20
Input
20
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4
Output
41

Note

In the first example, buy a share at 5, buy another at 4, sell one at 9 and another at 12. Then buy at 2 and sell at 10. The total profit is  - 5 - 4 + 9 + 12 - 2 + 10 = 20.

这道题是优先队列的应用,不过我还是没想到,太菜了

#include<iostream>
#include<queue>
typedef long long ll;
using namespace std;
int main()
{
    int n;
    ll ans=0,x;
    priority_queue<ll,vector<ll>,greater<ll> >q;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        scanf("%lld",&x);
        q.push(x);
        if(q.top()<x)
        {
            ans+=x-q.top();
            q.pop();
            q.push(x);
        }
    }
    cout<<ans<<endl;
    return 0;
 } 

X-Plosives

You are not a secret agent but only a guy in a delivery agency with one dangerous problem: receive binding pairs in sequential order and place them in a cargo ship. However, you must avoid placing in the same room an explosive association. So, after placing a set of pairs, if you receive one pair that might produce an explosion with some of the pairs already in stock, you must refuse it, otherwise, you must accept it. An example. Lets assume you receive the following sequence: A+B, G+B, D+F, A+E, E+G, F+H. You would accept the first four pairs but then refuse E+G since it would be possible to make the following explosive with the previous pairs: A+B, G+B, A+E, E+G (4 pairs with 4 simple compounds). Finally, you would accept the last pair, F+H. Compute the number of refusals given a sequence of binding pairs.
Input
The input will contain several test cases, each of them as described below. Consecutive test cases are separated by a single blank line. Instead of letters we will use integers to represent compounds. The input contains several lines. Each line (except the last) consists of two integers (each integer lies between 0 and 105) separated by a single space, representing a binding pair. Each test case ends in a line with the number ‘-1’. You may assume that no repeated binding pairs appears in the input.
Output
For each test case, the output must follow the description below. A single line with the number of refusals.
Sample Input
1 2 3 4 3 5 3 1 2 3 4 1 2 6 6 5 -1
Sample Output

3

这是一道并查集的题,好不容易想到了并查集,但在输入那里栽了,磨蹭了好久,还是思维不够灵活,脑子一时没转过来

一种化合物两种元素,但是n种化合物n种元素会爆炸,输出不要的化合物,一开始看完题很难想到并查集,但是后来一想,n种化合物应该有n+1种元素,但这时如果再出现一种化合物n+1种还是n+1个元素,则爆炸,说明出现了环,使用并查集,若所给元素出现在同一个集合里,就不行

#include<iostream>
#include<cstdio>
#include<vector> 
using namespace std;
const int maxn=1e5+10;
int fu[maxn];
void init()
{
    for(int i=0;i<=100010;i++)
       fu[i]=i;
}
int find(int x)
{
    if(x!=fu[x])
    {
        int t=fu[x];
        fu[x]=find(t);
    }
    return fu[x];
}
int main()
{
    int a,b;
    while(~scanf("%d",&a))
    {
        int ans=0;
        if(a==-1) break;
        init();
        while(a!=-1)
        {
            scanf("%d",&b);
            int fa=find(a);
            int fb=find(b);
            if(fa==fb)
            {
                ans++;
            }
            else
            {
                fu[fa]=fb;
            }
            cin>>a;
        }
        printf("%d\n",ans);
    }
    return 0;
} 

 Corporative Network

A very big corporation is developing its corporative network. In the beginning each of the N enterprises of the corporation, numerated from 1 to N, organized its own computing and telecommunication center. Soon, for amelioration of the services, the corporation started to collect some enterprises in clusters, each of them served by a single computing and telecommunication center as follow. The corporation chose one of the existing centers I (serving the cluster A) and one of the enterprises J in some other cluster B (not necessarily the center) and link them with telecommunication line. The length of the line between the enterprises I and J is |I−J|(mod1000). In such a way the two old clusters are joined in a new cluster, served by the center of the old cluster B. Unfortunately after each join the sum of the lengths of the lines linking an enterprise to its serving center could be changed and the end users would like to know what is the new length. Write a program to keep trace of the changes in the organization of the network that is able in each moment to answer the questions of the users. Your program has to be ready to solve more than one test case.
Input
The first line of the input file will contains only the number T of the test cases. Each test will start with the number N of enterprises (5 ≤ N ≤ 20000). Then some number of lines (no more than 200000) will follow with one of the commands:
E I — asking the length of the path from the enterprise I to its serving center in the moment; I I J — informing that the serving center I is linked to the enterprise J.
The test case finishes with a line containing the word ‘O’. The ‘I’ commands are less than N.
Output
The output should contain as many lines as the number of ‘E’ commands in all test cases with a single number each — the asked sum of length of lines connecting the corresponding enterprise with its serving center.
Sample Input
1 4 E 3 I 3 1 E 3 I 1 2 E 3 I 2 4 E 3 O
Sample Output
0 2 3 5

此题目的很明确,更新权值的并查集

O停止

E查询x到根节点的距离

I x连到y,并且他们的距离为abs(x-y)%1000

#include<iostream>
using namespace std;
 const int maxn=1e5;
int fu[maxn],dis[maxn];
int init(int n)
{
    for(int i=0;i<=n;i++)
    {
        fu[i]=i;
        dis[i]=0;
    }
       
}
int find(int x)
{
    if(x!=fu[x])
    {
        int t=fu[x];
        fu[x]=find(t);
        dis[x]+=dis[t];
    }
    return fu[x];
}
int abs(int x)
{
    return x>0?x:-x;
}

int main()
{
    int t,n,x,y;
    string s;
    cin>>t;
    while(t--)
    {
        cin>>n;
        init(n);
        while(cin>>s)
        {
            if(s[0]=='O')break;
            if(s[0]=='E')
            {
                cin>>x;
                find(x);
                cout<<dis[x]<<endl;
            }
            if(s[0]=='I')
            {
                cin>>x>>y;
                fu[x]=y;
                dis[x]=abs(x-y)%1000;
            }
        }
    }
    return 0;
}

 选课

又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合。你来帮帮他吧。(xhd认为一样学分的课没区别)

Input输入数据的第一行是一个数据T,表示有T组数据。
每组数据的第一行是两个整数n(1 <= n <= 40),k(1 <= k <= 8)。
接着有k行,每行有两个整数a(1 <= a <= 8),b(1 <= b <= 10),表示学分为a的课有b门。
Output对于每组输入数据,输出一个整数,表示学n个学分的组合数。
Sample Input

2
2 2
1 2
2 1
40 8
1 1
2 2
3 2
4 2
5 8
6 9
7 6
8 8

Sample Output

2
445

用一个数组记录每个对应分值的组合数,然后根据数据相加
#include <iostream>
using namespace std;
int main ()
{
    int t,n,m,i,j,a,b,d[50];  //dp记录当前学分的组合数
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(i=d[0]=1;i<50;i++)
           d[i]=0;
        while(m--)
        {
            cin>>a>>b;
            for(i=n;i>=a;i--)    //学分 
              for(j=1;j<=b;j++)    //课程 
                 if(j*a<=i)        //如果当前学分能加上得分且不过界,组合数相加 
                   d[i]+=d[i-j*a];    
        }
        cout<<d[n]<<endl;
    }
    return 0;
}

 

posted @ 2019-07-19 17:12  蓉~  阅读(277)  评论(0编辑  收藏  举报