POJ

poj 2785 4 Values whose Sum is 0

Time Limit: 15000MS        Memory Limit: 228000K
Total Submissions: 21471        Accepted: 6469
Case Time Limit: 5000MS
Description

The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
Input

The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228 ) that belong respectively to A, B, C and D .
Output

For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
Sample Output

5
Hint

Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

 

折半枚举, 求四个和为0, 先将两个数组的和枚举保存然后排序(n2+ nlogn), 然后枚举另两个数组判断其和是否在前面的数组里(二分查找 n2log n).

#include <iostream>
#include <cstdio>
#include<algorithm>
using namespace std;
const int N = 4001;
int a[4][N];
int cd[N * N];
typedef long long ll;
int main(int argc, char *argv[])
{
    int n;
    ll cnt = 0;
    //freopen("in.txt", "r", stdin);
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 4; j++) {
            scanf("%d", &a[j][i]);
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cd[i * n + j] = a[2][i] + a[3][j];
        }
    }
    sort(cd, cd + n * n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int temp = -(a[0][i] + a[1][j]);
            cnt += upper_bound(cd, cd + n * n, temp) - lower_bound(cd, cd + n * n, temp);
        }
    }
    printf("%lld\n", cnt);        
    return 0;
}
View Code

poj 3061 Subsequence

Subsequence
Time Limit: 1000MS        Memory Limit: 65536K
Total Submissions: 14024        Accepted: 5930
Description

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.
Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.
Sample Input

2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output

2
3

1 尺取法,枚举序列的左右位置(N2), 优化方法 若Q(i) = j是满足要求的起点为i的最小j, 则Q(i + 1)  >= j, 所以尺取法不断变换终点即可(N).记得特判没有解的情况。

2或者S(i, j) = S(0, j) - S(0, i), 计算0到每个位置的序列和存起来(N), 对每个起点用二分查找大于S的(NlogN)。 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int main(int argc, char *argv[])
{
    int t, n, s;
    //freopen("in.txt", "r", stdin);
    scanf("%d", &t);
    while (t--) {
        scanf("%d %d", &n, &s);
        int * a = new int [n + 5];
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
        }
        int ans = n + 1;
        int sum = 0;
        int left = 0;
        int right = 0;
        while (true) {
            while (sum < s && right < n) {
                sum += a[right++];
            }
            if (sum < s) {
                break;
            }
            ans = min(ans, right - left);
            sum -= a[left++];
        }
        printf("%d\n", ans > n ? 0 : ans);
    }    
    return 0;
View Code

 POJ 3614 Sunscreen

Description

To avoid unsightly burns while tanning, each of the C (1 ≤ C ≤ 2500) cows must cover her hide with sunscreen when they're at the beach. Cow i has a minimum and maximum SPF rating (1 ≤ minSPFi ≤ 1,000; minSPFi ≤ maxSPFi ≤ 1,000) that will work. If the SPF rating is too low, the cow suffers sunburn; if the SPF rating is too high, the cow doesn't tan at all........

The cows have a picnic basket with L (1 ≤ L ≤ 2500) bottles of sunscreen lotion, each bottle i with an SPF rating SPFi (1 ≤ SPFi ≤ 1,000). Lotion bottle i can cover coveri cows with lotion. A cow may lotion from only one bottle.

What is the maximum number of cows that can protect themselves while tanning given the available lotions?

Input

* Line 1: Two space-separated integers: C and L
* Lines 2..C+1: Line i describes cow i's lotion requires with two integers: minSPFi and maxSPFi 
* Lines C+2..C+L+1: Line i+C+1 describes a sunscreen lotion bottle i with space-separated integers: SPFi and coveri

Output

A single line with an integer that is the maximum number of cows that can be protected while tanning

Sample Input

3 2
3 10
2 5
1 5
6 2
4 1
Sample Output

2
View Code

题意:有一堆一维区间和 一堆点,求点在区间内的最大匹配对数。贪心解决,对某一个点,当它落在多个区间使,优先满足上限小的区间。(先排序,然后所有满足的区间用优先级队列存储)

#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef pair<int ,int> p;
p cow[2510];
p bottle[2510];
int main () {
    int c, l;
    //freopen("in.txt", "r", stdin);
    scanf("%d%d", &c, &l);
    for (int i = 0; i < c; ++i) {
        scanf("%d%d", &cow[i].first, &cow[i].second);
    }
    for (int i = 0; i < l; i++) {
        scanf("%d%d", &bottle[i].first, &bottle[i].second);
    }
    sort(cow, cow + c);
    sort(bottle, bottle + l);
    int cur = 0;  //current cow 
    int ans = 0;
    priority_queue <int, vector<int>, greater<int> > q;
    for (int i = 0; i < l; i++) {
        int spf = bottle[i].first;
        int num = bottle[i].second;
        while (cur < c && spf >= cow[cur].first) {
            q.push(cow[cur++].second);
        }
        while (num && !q.empty()) {
            int maxSpf = q.top();
            q.pop();
            if (maxSpf >= spf) {
                num--;
                ans++;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

=== 优先级队列 ====

POJ 2010 Moo University - Financial Aid

Description

Bessie noted that although humans have many universities they can attend, cows have none. To remedy this problem, she and her fellow cows formed a new university called The University of Wisconsin-Farmside,"Moo U" for short. 

Not wishing to admit dumber-than-average cows, the founders created an incredibly precise admission exam called the Cow Scholastic Aptitude Test (CSAT) that yields scores in the range 1..2,000,000,000. 

Moo U is very expensive to attend; not all calves can afford it.In fact, most calves need some sort of financial aid (0 <= aid <=100,000). The government does not provide scholarships to calves,so all the money must come from the university's limited fund (whose total money is F, 0 <= F <= 2,000,000,000). 

Worse still, Moo U only has classrooms for an odd number N (1 <= N <= 19,999) of the C (N <= C <= 100,000) calves who have applied.Bessie wants to admit exactly N calves in order to maximize educational opportunity. She still wants the median CSAT score of the admitted calves to be as high as possible. 

Recall that the median of a set of integers whose size is odd is the middle value when they are sorted. For example, the median of the set {3, 8, 9, 7, 5} is 7, as there are exactly two values above 7 and exactly two values below it. 

Given the score and required financial aid for each calf that applies, the total number of calves to accept, and the total amount of money Bessie has for financial aid, determine the maximum median score Bessie can obtain by carefully admitting an optimal set of calves. 

Input

* Line 1: Three space-separated integers N, C, and F 

* Lines 2..C+1: Two space-separated integers per line. The first is the calf's CSAT score; the second integer is the required amount of financial aid the calf needs 
Output

* Line 1: A single integer, the maximum median score that Bessie can achieve. If there is insufficient money to admit N calves,output -1. 
Sample Input

3 5 70
30 25
50 21
20 20
5 18
35 30
Sample Output

35
Hint

Sample output:If Bessie accepts the calves with CSAT scores of 5, 35, and 50, the median is 35. The total financial aid required is 18 + 30 + 21 = 69 <= 70. 
View Code

题意;有C只羊准备入学,每只羊有考试分数和所需生活费,学校只能招N人(奇数),且最多提供F的生活费, 目标:最大化招生分数的中位数。

题解:枚举处于中位数的羊即可。 分别计算当前羊为中位数时,左边和右边的最小费用(优先级队列递推),加起来即可。

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct cow {
    int score;
    int money;
    int left;
    int right;
};
bool cmp (cow x, cow y) {
    return x.score > y.score;
}
cow cows[100010];
int main() {
    int n, c, f;
    //freopen("in.txt", "r", stdin);
    scanf("%d%d%d", &n, &c, &f);
    for (int i = 0; i < c; i++) {
        scanf("%d %d", &cows[i].score, &cows[i].money);        
    }
    sort(cows, cows + c, cmp);
    
    //update left
    int curmoney = 0;
    priority_queue<int> qleft;
    for (int i = 0; i < c; i++) {
        if (i >= n / 2) {
            cows[i].left = curmoney;
            curmoney += cows[i].money;
            qleft.push(cows[i].money);
            curmoney -= qleft.top();
            qleft.pop();
        } else {
            qleft.push(cows[i].money);
            curmoney += cows[i].money;
        }
    }
    //update right
    curmoney = 0;
    priority_queue<int> qright;
    for (int i = c - 1; i >= 0; i--) {
        if (i < c - n / 2) {
            cows[i].right = curmoney;
            curmoney += cows[i].money;
            qright.push(cows[i].money);
            curmoney -= qright.top();
            qright.pop();
        } else {
            qright.push(cows[i].money);
            curmoney += cows[i].money;
        }
    }
    int ans = -1;
    for (int i = n / 2; i < c - n / 2; i++) {
        if ((cows[i].money + cows[i].left + cows[i].right) <= f) {
            ans = cows[i].score;
            break;
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

=== union find ==== 

POJ 2236 Wireless Network

Description

An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have set up a wireless network with the lap computers, but an unexpected aftershock attacked, all computers in the network were all broken. The computers are repaired one by one, and the network gradually began to work again. Because of the hardware restricts, each computer can only directly communicate with the computers that are not farther than d meters from it. But every computer can be regarded as the intermediary of the communication between two other computers, that is to say computer A and computer B can communicate if computer A and computer B can communicate directly or there is a computer C that can communicate with both A and B. 

In the process of repairing the network, workers can take two kinds of operations at every moment, repairing a computer, or testing if two computers can communicate. Your job is to answer all the testing operations. 
Input

The first line contains two integers N and d (1 <= N <= 1001, 0 <= d <= 20000). Here N is the number of computers, which are numbered from 1 to N, and D is the maximum distance two computers can communicate directly. In the next N lines, each contains two integers xi, yi (0 <= xi, yi <= 10000), which is the coordinate of N computers. From the (N+1)-th line to the end of input, there are operations, which are carried out one by one. Each line contains an operation in one of following two formats: 
1.    "O p" (1 <= p <= N), which means repairing computer p. 
2.    "S p q" (1 <= p, q <= N), which means testing whether computer p and q can communicate. 

The input will not exceed 300000 lines. 
Output

For each Testing operation, print "SUCCESS" if the two computers can communicate, or "FAIL" if not.
Sample Input

4 1
0 1
0 2
0 3
0 4
O 1
O 2
O 4
S 1 4
O 3
S 1 4
Sample Output

FAIL
SUCCESS
View Code

水题,最基本的并查集即可。

#include <iostream>  
#include <string.h>  
#include <stdio.h>  
  
using namespace std;  
const int N = 1005;  
  
struct Point  
{  
    int x,y;  
};  
  
Point p[N];  
int repaired[N];  
int pre[N],rank[N];  
  
int dist(Point A,Point B)  
{  
    return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);  
}  
  
void Init(int n)  
{  
    for(int i=1;i<=n;i++)  
    {  
        pre[i] = i;  
        rank[i] = 1;  
    }  
}  
  
int Find(int x)  
{  
    if(pre[x] != x)  
        pre[x] = Find(pre[x]);  
    return pre[x];  
}  
  
void Union(int x,int y)  
{  
    x = Find(x);  
    y = Find(y);  
    if(x == y) return;  
    if(rank[x] >= rank[y])  
    {  
        pre[y] = x;  
        rank[x] += rank[y];  
    }  
    else  
    {  
        pre[x] = y;  
        rank[y] += rank[x];  
    }  
}  
  
int main()  
{  
    char ch[5];  
    int n,d,x,y;  
    scanf("%d%d",&n,&d);  
    for(int i=1;i<=n;i++)  
        scanf("%d%d",&p[i].x,&p[i].y);  
    int cnt = 0;  
    Init(n);  
    while(~scanf("%s",ch))  
    {  
        if(ch[0] == 'O')  
        {  
            scanf("%d",&x);  
            for(int i=0;i<cnt;i++)  
            {  
                if(dist(p[repaired[i]],p[x]) <= d*d)  
                    Union(repaired[i],x);  
            }  
            repaired[cnt++] = x;  
        }  
        else  
        {  
            scanf("%d%d",&x,&y);  
            x = Find(x);  
            y = Find(y);  
            if(x == y) puts("SUCCESS");  
            else       puts("FAIL");  
        }  
    }  
    return 0;  
} 
View Code

 

posted @ 2017-04-05 22:27  hxidkd  阅读(231)  评论(0编辑  收藏  举报