slove  2/10

rank  261

补题   5/10

--------------------------------------------------------

https://ac.nowcoder.com/acm/contest/883#question

B、Crazy Binary String

题意:给一个01串,求出使01个数相等的最长子串和最长子序列,输出长度。

思路:记录每个位置前缀的0-1的数量,如果这个数量是第一次出现,存一下当前这个数量对应的下标,否则,直接更新答案

Code:

#include <bits/stdc++.h>
using namespace std;
char s[100005];
map<int, int>mp;
int main()
{
	int n;
	scanf("%d", &n);
	scanf("%s", s);
	int cnt10 = 0, ans = 0;
	int one = 0, zero = 0;
	mp[0] = -1;
	for (int i = 0; i < n; i++)
	{
		if (s[i] == '1')
		{
			cnt10++;
			one++;
		}
		else
		{
			cnt10--;
			zero++;
		}
		if (mp[cnt10] == 0)
			mp[cnt10] = i;
		else
			ans = max(ans, i - mp[cnt10]);
	}
	int ans1 = min(one, zero);
	ans1 *= 2;
	printf("%d %d", ans,ans1);
}

F、Planting Trees

题意:给一个n*n的矩阵,定义一个矩阵合法,当且仅当矩阵的最大值减最小值小于等于M,要求你找出合法子矩阵的最大面积。

思路:暴力上下边界和右边界,然后单调栈维护左端点的最大值和最小值,如果当前矩阵不合法,那么左端点肯定要右移,然后维护最大最小值就可以了

Code:

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int maxn[1005], minn[1005];//维护纵坐标为i时,一行的前缀最大最小值
//deque<int>demax, demin;
int demax[1005], demin[1005];
int head1, tail1, head2, tail2;
int main()
{
	int n, m;
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				scanf("%d", &a[i][j]);
		int ans = 0;
		for (int i = 1; i <= n; i++)//上边界
		{
			for (int j = 1; j <= n; j++)
			{
				maxn[j] = 0;
				minn[j] = 100005;
			}
			for (int j = i; j <= n; j++)//下边界
			{
				//demin.clear(), demax.clear();
				head1 = 0, tail1 = 0, head2 = 0, tail2 = 0;
				int index = 0;//左端点
				for (int k = 1; k <= n; k++)//右边界
				{
					maxn[k] = max(maxn[k], a[j][k]);
					minn[k] = min(minn[k], a[j][k]);
				}
				for (int k = 1; k <= n; k++)//右边界
				{
					while (head1 < tail1 && maxn[demax[tail1 - 1]] <= maxn[k])//维护最大值的递减序列
						tail1--;
					while (head2 < tail2 && minn[demin[tail2 - 1]] >= minn[k])//维护最小值的递增序列
						tail2--;
					demax[tail1++] = k;
					demin[tail2++] = k;
					while (head1 < tail1 && head2 < tail2 && maxn[demax[head1]] - minn[demin[head2]] > m)//如果此时区间不满足于要求,左端点右移
					{
						if (demax[head1] < demin[head2])
						{
							index = demax[head1];//更新左端点
							head1++;
						}
						else
						{
							index = demin[head2];//更新左端点
							head2++;
						}
					}
					ans = max(ans, (j - i + 1) * (k - index));
				}
			}
		}
		printf("%d\n", ans);
	}
}

G、Removing Stones

给一个区间,找出所有满足区间和大于等于区间最大值*2的区间的数量。

对于每个点,我们假设这个点是区间的最大值,那么左端点一定小于等于 i ,右端点一定大于等于 i ,那么我们可以知道他可以往左边取最多多少个数字,然后每次判断是否还能向右取,右端点的数量就是固定左端点的答案贡献,然后每次将左端点右移,重复上述步骤,知道左端点为空

#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
ll a[300005];
int main()
{
	int T;
	sc("%d", &T);
	while (T--)
	{
		int n;
		sc("%d", &n);
		for (int i = 1; i <= n; i++)
			sc("%lld", &a[i]);
		ll ans = 0;
		for (int i = 1; i <= n; i++)
		{
			int l = i, r = i;
			ll sum = 0;
			//固定左端点的值
			while (l > 1 && sum + a[l - 1] < a[i])
				sum += a[--l];
			while (l <= i)
			{
				//判断右端点的个数
				while (r < n && sum + a[r + 1] < a[i])
					sum += a[++r];
				ans += r - i + 1;
				sum -= a[l++];//左端点右移
			}
		}
		printf("%lld\n", 1LL * n * (n + 1) / 2 - ans);
	}
}

H、Magic Line

题意:给你N个点,N是偶数,要求你画出一条直线,将这N个点划分为两个集合,输出直线的左右顶点(要是整数)

思路:排个序。找到分界点,如果不在同一行,瞎搞,如果在同一行y,取(-3000,y-1),然后搞一下公式,找到这个点和两个分界点的线与9e8的交点,然后在他们的交点上随便选一个整数点就可以了。

Code:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <algorithm>
#include <string.h>
#include <queue>
#define ll long long
const double eps = 1e-6;
const double PI = acos(-1.0); // PI = 180°= 3.14 
using namespace std;
//判断符号
int sign(double x)
{
	if (fabs(x) < eps)
		return 0;
	return x > 0 ? 1 : -1;
}
struct node
{
	ll x;
	ll y;
	node operator + (const node& other) { return node{ x + other.x, y + other.y }; }
	node operator - (const node& other) { return node{ x - other.x, y - other.y }; }
	node operator * (int k) { return node{ x * k, y * k }; }
	node operator / (int k) { return node{ x / k, y / k }; }
};
//叉积
ll cross(node a, node b)
{
	return a.x * b.y - b.x * a.y;
}
double calc(double a, double b, double c, double d)
{
	double ans = (d - b) / (c - a) * 900000000 - (c * (d - b) / (c - a)) + d;
	return ans;
}
node in[100005];
int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		int n;
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
		{
			scanf("%lld%lld", &in[i].x, &in[i].y);
		}
		sort(in, in + n, [](node q, node w) {
			if (q.y == w.y)
				return q.x < w.x;
			return q.y > w.y;
		});
		node a = in[n / 2 - 1];
		node b = in[n / 2];
		if (a.y != b.y)
		{
			printf("-1000000000 %d 1000000000 %d\n", b.y, a.y);
			continue;
		}
		int now = a.y;
		node o = node{ -3100,now - 1 };
		node l1 = node{ 900000000,1 };
		node l2 = node{ 900000000,-1 };
		double y1 = calc(o.x, o.y, a.x, a.y);
		double y2 = calc(o.x, o.y, b.x, b.y);
		int x = 900000000;
		int y = 0;
		for (int i = (double)(y1 - 2); i > y2; i--)
		{
			y = i;
			break;
		}
		printf("-3100 %d %d %d\n", now - 1, x, y);
		qwe:;
	}
}

J、LRU management

题意:两个操作,第一个操作是插入,如果之前存在这个地址,那么将这个地址移到最后面,否则在最后面加入这个地址,第二个操作是查询操作,要先找到某个地址,然后将这个地址前移或者后移或者他本身,并且输出这个地址的值。如果越界或者没找到输出 Invalid

STL瞎搞,map存list中对应的迭代器,就可以logn查找到第N个。

Code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
#define Pair pair<string,int>
list<Pair>v;
map<string, list<Pair>::iterator>mp;

struct ioss {
#define endl '\n'
	static const int LEN = 20000000;
	char obuf[LEN], * oh = obuf;
	std::streambuf* fb;
	ioss()
	{
		ios::sync_with_stdio(false);
		cin.tie(NULL);
		cout.tie(NULL);
		fb = cout.rdbuf();
	}
	inline char gc() {

		static char buf[LEN], * s, * t, buf2[LEN];
		return (s == t) && (t = (s = buf) + fread(buf, 1, LEN, stdin)), s == t ? -1 : *s++;
	}
	inline ioss& operator >> (long long& x) {
		static char ch, sgn, * p;
		ch = gc(), sgn = 0;
		for (; !isdigit(ch); ch = gc()) { if (ch == -1)return *this; sgn |= ch == '-'; }
		for (x = 0; isdigit(ch); ch = gc())x = x * 10 + (ch ^ '0');
		sgn && (x = -x); return *this;
	}
	inline ioss& operator >> (int& x) {
		static char ch, sgn, * p;
		ch = gc(), sgn = 0;
		for (; !isdigit(ch); ch = gc()) { if (ch == -1)return *this; sgn |= ch == '-'; }
		for (x = 0; isdigit(ch); ch = gc())x = x * 10 + (ch ^ '0');
		sgn && (x = -x); return *this;
	}
	inline ioss& operator >> (char& x)
	{
		static char ch;
		for (; !isalpha(ch); ch = gc())
		{
			if (ch == -1)return *this;
		}
		x = ch;
		return *this;
	}
	inline ioss& operator >> (string& x)
	{
		static char ch, * p, buf2[LEN];
		for (; !isalpha(ch) && !isdigit(ch); ch = gc())
			if (ch == -1)return *this;
		p = buf2;
		for (; isalpha(ch) || isdigit(ch); ch = gc())
			* p = ch, p++;
		*p = '\0';
		x = buf2;
		return *this;
	}
	inline ioss& operator <<(string& c)
	{
		for (auto& p : c)
			this->operator<<(p);
		return *this;
	}
	inline ioss& operator <<(const char* c)
	{
		while (*c != '\0')
		{
			this->operator<<(*c);
			c++;
		}
		return *this;
	}
	inline ioss& operator <<(const char& c) {
		oh == obuf + LEN ? (fb->sputn(obuf, LEN), oh = obuf) : 0;
		*oh++ = c;
		return *this;
	}
	inline ioss& operator <<(int x) {
		static int buf[30], cnt;
		if (x < 0)
			this->operator<<('-'), x = -x;
		if (x == 0)
			this->operator<<('0');
		for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
		while (cnt) this->operator<<((char)buf[cnt--]);
		return *this;
	}
	inline ioss& operator <<(long long x) {
		static int buf[30], cnt;
		if (x < 0)
			this->operator<<('-'), x = -x;
		if (x == 0)
			this->operator<<('0');
		for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
		while (cnt) this->operator<<((char)buf[cnt--]);
		return *this;
	}
	~ioss()
	{
		fb->sputn(obuf, oh - obuf);
	}
} io;

int main()
{
	int T;
	io >> T;
	while (T--)
	{
		int n, m;
		io >> n >> m;
		v.clear();
		mp.clear();
		int v_sz = 0;
		while (n--)
		{
			int op, x;
			string s;
			io >> op >> s >> x;
			if (op == 0)//find s and move end
			{
				if (mp.find(s) != mp.end())//erase s
				{
					x = mp[s]->second;
					io << x << endl;
					v.erase(mp[s]);
					v.push_back(Pair{ s,x });
					auto it = v.end();
					it--;
					mp[s] = it;
				}
				else
				{
					if (v_sz == m)
					{
						mp.erase(v.begin()->first);
						v.erase(v.begin());
					}
					else
						v_sz++;
					io << x << endl;
					v.push_back(Pair{ s,x });
					auto it = v.end();
					it--;
					mp[s] = it;
				}
			}
			else//find s and add x to value
			{
				if (mp.find(s) == mp.end())
				{
					io << "Invalid" << endl;
					continue;
				}
				auto it = mp[s];
				if (x == 0)
				{
					io << it->second << endl;
				}
				else if (x == -1)
				{
					if (it == v.begin())
						io << "Invalid" << endl;
					else
					{
						it--;
						io << it->second << endl;
					}
				}
				else
				{
					it++;
					if (it == v.end())
						io << "Invalid" << endl;
					else
					{
						io << it->second << endl;
					}
				}
			}
		}
	}
}