POJ-1083 Moving Tables(imos算法)

这一题有两个陷阱:

  1. 给出的起始点可能小于终点 ,所以必须要加个判断,让第二个数大于第一个数
  2. 区间算的时候,一定是奇数到偶数,才能做到真正的区间全覆盖。所以如果第二个数是奇数,要加一变为偶数;第一个数为偶数,要减一变为奇数

知识点:

  1. 这道题主要用到了imos算法。很好用的算法,详见:http://www.hankcs.com/program/algorithm/imos_method.html
  2. max_element()这个在 algorithm 的头文件里,非常好用,可以返回从begin到end这中间的最大值,作用区间是一个大的范围。
    注意区别 max(),max是返回a和b这两个数中最大值,作用区间是两个变量。
    详细区别请看:https://www.cnblogs.com/ChrisCoder/p/10171134.html
  3. 长时间没有练习了,导致犯了一个很低级的错误,数组的长度不是 sizeof(a),而是 sizeof(a)/sizeof(a[0]) 或者 sizeof(数组名)/sizeof(数组类型)
  4. 注意输入多组数据的时候,每次需要先把上组数据用到的变量或数据结构清空

方法一:

方法一的好处在于,时间复杂度低,是O(n) (不考虑外层控制T,只考虑内层),但是牺牲了空间复杂度,用了双vector或者双数组或者结构体

#include <iostream>
#include <stdlib.h>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int maxn = 405;

int main()
{
	int T;
	int N;
	int a, b;
	int table[maxn];
	vector<int> numIn;    // 用结构体也可以实现
	vector<int> numOut;
	/*
	const int maxn = 200;
	typedef struct member{
		int s;
		int j;
	}member;
	member num[maxn];
   */
	cin >> T;
	while (T--)      // 注意输入多组数据的时候,每次需要先把上组数据用到的变量或数据结构清空
	{
		cin >> N;
		numIn.clear();
		numOut.clear();
		memset(table, 0, sizeof(table));
		for (int i = 0; i < N; i++)
		{
			cin >> a >> b;
			if (a > b)
				swap(a, b);
			if (a % 2 == 0)
				a = a - 1;
			if (b % 2 == 1)
				b = b + 1;
			numIn.push_back(a);
			numOut.push_back(b);
		}

		for (int i = 0; i < numIn.size(); i++)
		{
			table[numIn[i]]++;
			table[numOut[i]]--;
		}

		for (int i = 1; i < maxn; i++)     // 可不是 sizeof(table)
		{
			table[i] += table[i - 1];
		}
		int sum = *max_element(table, table + maxn);
		cout << sum*10 << endl;
	}
}

方法二:

方法二的好处在于,空间复杂度低,没有用到额外的数据结构,但是时间复杂度高,是O(n^2) (不考虑外层控制T,只考虑内层)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn=400+10;
const int inf=0xffffff;
int t[maxn];
int main()
{
     int T,n,a,b;
     cin>>T;
     while(T--)
     {
         scanf("%d",&n);
         mem(t);
         int ma=-inf;
         for(int i=0;i<n;i++)
         {
             scanf("%d%d",&a,&b);
             if(a>b) swap(a,b);
             if(a%2==0) a--;
             if(b%2==1) b++;
             for(int j=a;j<=b;j++)
               t[j]++;
         }
         for(int i=1;i<=400;i++)
         {
             ma=max(ma,t[i]);
         }
         cout<<10*ma<<endl;
     }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值