BestCoder Round #20 B,C

畫船聽雨發表於2014-12-02

B:對於座標先進行離散化,然後線性的掃一遍,常見的處理方式。

lines

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 644    Accepted Submission(s): 298


Problem Description
John has several lines. The lines are covered on the X axis. Let A is a point which is covered by the most lines. John wants to know how many lines cover A.
 

Input
The first line contains a single integer T(1T100)(the data for N>100 less than 11 cases),indicating the number of test cases.
Each test case begins with an integer N(1N105),indicating the number of lines.
Next N lines contains two integers Xi and Yi(1XiYi109),describing a line.
 

Output
For each case, output an integer means how many lines cover A.
 

Sample Input
2 5 1 2 2 2 2 4 3 4 5 1000 5 1 1 2 2 3 3 4 4 5 5
 

Sample Output
3 1
 

Source
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <math.h>
#include <time.h>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
///#define LL long long
#define LL __int64
#define INF 0x3f3f3f
#define PI acos(-1)
#define mod 1000000007


using namespace std;


const int maxn = 200010;

int num[maxn];
int dx[maxn];
int lx[maxn];
int ly[maxn];

struct node
{
    int x, y;
}f[maxn];

int Find(int x, int n)
{
    int l = 0;
    int r = n-1;
    while(l <= r)
    {
        int mid = (l+r)/2;
        if(dx[mid] == x) return mid;
        if(dx[mid] > x) r = mid-1;
        else l = mid+1;
    }
    return -1;

}

int main()
{
    int T;
    cin >>T;
    while(T--)
    {
        int n;
        int ans = 0;
        scanf("%d",&n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d %d",&f[i].x, &f[i].y);
            num[ans++] = f[i].x;
            num[ans++] = f[i].y;
        }
        sort(num, num+ans);
        int cnt = 0;
        dx[cnt++] = num[0];
        for(int i = 1; i < ans; i++)
        {
            if(num[i] == dx[cnt-1]) continue;
            dx[cnt++] = num[i];
        }
        memset(lx, 0, sizeof(lx));
        memset(ly, 0, sizeof(ly));
        for(int i = 0; i < n; i++)
        {
            int x = Find(f[i].x, cnt);
            int y = Find(f[i].y, cnt);
            lx[x]++;
            ly[y]--;
        }
        int Max = 0;
        int sum = 0;
        for(int i = 0; i < cnt; i++)
        {
            sum += lx[i];
            Max = max(sum, Max);
            sum += ly[i];
        }
        cout<<Max<<endl;
    }
    return 0;
}
C:最長上升子序列的改版,要求在A和B最多可以交換m次的前提下,找到A的一條最長上升子序列。

直接想的話dp(i, j, k)已經交換了i次,位置j處,取A(k == 0)或者取B(k == 1)時的最大長度為多少。

三層會1000*1000*1000TLE到死啊。

有m顆線段樹維護每次找到交換了i次位置為j的最長子序列是多少。

magic balls

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 438    Accepted Submission(s): 130


Problem Description
The town of W has N people. Each person takes two magic balls A and B every day. Each ball has the volume ai and bi. People often stand together. The wizard will find the longest increasing subsequence in the ball A. The wizard has M energy. Each point of energy can change the two balls’ volume.(swap(ai,bi)).The wizard wants to know how to make the longest increasing subsequence and the energy is not negative in last. In order to simplify the problem, you only need to output how long the longest increasing subsequence is.
 

Input
The first line contains a single integer T(1T20)(the data for N>100 less than 6 cases), indicating the number of test cases.
Each test case begins with two integer N(1N1000) and M(0M1000),indicating the number of people and the number of the wizard’s energy. Next N lines contains two integer ai and bi(1ai,bi109),indicating the balls’ volume.
 

Output
For each case, output an integer means how long the longest increasing subsequence is.
 

Sample Input
2 5 3 5 1 4 2 3 1 2 4 3 1 5 4 5 1 4 2 3 1 2 4 3 1
 

Sample Output
4 4
 

Source
 
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
#define LL long long
//#define LL long long
#define INF 0x3f3f3f
#define PI 3.1415926535898
#define mod 1000000007
#define rson mid+1, r, rt<<1|1
#define lson l, mid, rt<<1
#define root 0, ans-1, 1


const int maxn = 1001;

using  namespace std;

int dp[maxn][8001];
int dy[2*maxn], dx[2*maxn];
int num1[maxn], num2[maxn];

struct node
{
    int x, y;
}f[maxn];
int ans;

int Find(int x)
{
    int l = 0;
    int r = ans-1;
    while(l <= r)
    {
        int mid = (l+r)>>1;
        if(dy[mid] == x) return mid;
        else if(dy[mid] < x) l = mid+1;
        else r = mid-1;
    }
    return -1;
}


int Query(int m, int l, int r, int L, int R, int site)
{
    if(l == L && r == R) return dp[m][site];
    int mid = (L+R)>>1;
    if(r <= mid) return Query(m, l, r, L, mid, site<<1);
    else if(l > mid) return Query(m, l, r, mid+1, R, site<<1|1);
    else return max(Query(m, l, mid, L, mid, site<<1), Query(m, mid+1, r, mid+1, R, site<<1|1));
}

void Push_UP(int m, int site)
{
    dp[m][site] = max(dp[m][site<<1], dp[m][site<<1|1]);
}

void Updata(int m, int x, int d, int l, int r, int site)
{
    if(l == r)
    {
        dp[m][site] = d;
        return;
    }
    int mid = (l+r)>>1;
    if(x <= mid) Updata(m, x, d, l, mid, site<<1);
    else Updata(m, x, d, mid+1, r, site<<1|1);
    Push_UP(m, site);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n, m;
        scanf("%d %d",&n, &m);
        ans = 0;
        for(int i = 0; i < n; i++)
        {
            scanf("%d %d",&f[i].x, &f[i].y);
            dx[i<<1] = f[i].x;
            dx[i<<1|1] = f[i].y;
        }
        sort(dx, dx+2*n);
        dy[ans++] = dx[0];
        for(int i = 1; i < 2*n; i++)
        {
            if(dy[ans-1] == dx[i]) continue;
            dy[ans++] = dx[i];
        }
        for(int i = 0; i <= m ; i++)
            for(int j = 0; j <= 4*ans; j++) dp[i][j] = 0;
        int Max = 0;
        int sum1, sum2, xans;
        for(int i = 0; i < n; i++)
        {
            int x = Find(f[i].x);
            int y = Find(f[i].y);
            xans = 0;
            if(x) xans = Query(0, 0, x-1, 0, ans-1, 1);
            num1[0] = xans+1;
            Max = max(Max, xans+1);
            for(int j = 1; j <= i+1 && j <= m; j++)
            {
                sum1 = 0;
                sum2 = 0;
                if(j != i+1)
                {
                    if(x) sum1 = Query(j, 0, x-1, 0, ans-1, 1);
                    num1[j] = sum1+1;
                }
                if(y) sum2 = Query(j-1, 0, y-1, 0, ans-1, 1);
                num2[j] = sum2+1;
                xans = max(sum1, sum2);
                Max = max(Max, xans+1);
            }
            for(int j = 0; j <= i+1 && j <= m; j++)
            {
                if(j != i+1) Updata(j, x, num1[j], 0, ans-1, 1);
                if(!j) continue;
                Updata(j, y, num2[j], 0, ans-1, 1);
            }
        }
        printf("%d\n",Max);
    }
    return 0;
}



相關文章