有人说这场背景描述挺烂,不过我觉得还不错(
A题意有点烦,建议直接去看英文原文((
手动画图然后推个结论,挺简单的,不赘述了:
/*
ID: Loxilante
Time: 2020/08/07
Prog: CF1393A
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/stdc++.h>
#define rep(i, l, r) for(register int i = l; i < r; i++)
#define hrp(i, l, r) for(register int i = l; i <= r; i++)
#define rev(i, r, l) for(register int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn> inline tn next(void) { tn k; cin>>k; return k; }
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next<int>();
while(T--) cout<<(next<int>())/2+1<<endl;
clock_t InputFinished = clock();
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
/*
*/
B的意思是给你n和n根木棍,q和q个操作,对于每个操作+ x代表加入一根x长木棍,- x代表删去一根x长木棍,每次操作后输出能不能从中挑出8根木棍分别围成一个正方形和一个矩形(矩形能为正方形)。
(1 <= n,q <= 1e5)
仔细观察下题,其实就是让我们实现一个玩意儿,其中插入,删除,询问时间复杂度要小于(O(n+q))。
打cf的时候开始没什么头绪,我的思路也比较绕,不过如果模块化就可以很容易写出来:
首先考虑用cnt数组计数然后用vector存4根木棍相同和2根木棍相同的,这样插入是(O(1)),询问是(O(1)),可是删除是(O(n)),再加上这些操作最多要做q次,总复杂度是(O(qn)),直接T飞。
然后考虑使vector中木棍长度有序然后二分删除,可以先(O(nlogn))排序,类似插入排序思想插入,可是这样插入复杂度是(O(n)),总复杂度(O(n^2)),继续T飞。
等等,刚刚那个思路的前提是木棍长度有序,我不由自主地想到了set。
emmm,set用不了,因为木棍长度可能相同,set不允许元素重复,这时候我们英勇的multiset就出场啦。
multiset,C++98能用,是一个允许元素重复的set,也就是一个内部元素一直有序的容器。
这样的话,用multiset可以实现(O(logn))插入,multiset删除是(O(logn)),我们再二分(O(logn)),所以删除总复杂度是(O((logn)^2)),询问(O(1))。
然后考虑实现,可以维护两个multiset,一个four一个two,一个储存4根木棍相同和2根木棍相同的,再开一个cnt数组,然后你们都会的。
先考虑插入操作:
插入新木棍的时候我们让cnt[a]++;
当cnt[a] == 2时,我们把它插入two,注意但cnt[a] == 3时不能插入,这是一个坑。
然后当cnt[a] == 4时,我们把它插入four,同时cnt[a]清零,同时把two中的a删除。
然后再考虑删除操作:
我们先在four和two中二分找到木棍长度a,然后分类讨论:
如果two中找到了,那就将cnt[a]--; 如果cnt[a] == 1了,也就是有两个相同不成立了,就把a在two中删除。
如果two中没找到但是four中找到了,如果cnt[a] == 0,那就只有3个相同,就把a从four扔到two。
如果four和two都没找到,因为题目保证删除的木棍存在,所以只可能cnt[a] == 1,就把cnt[a]--;
最后是简单的询问操作:
如果four中有2个元素,也就是有(a a a a b b b b)的木棍,可以围成两个正方形,显然YES。
如果four中有1个元素,two中有两个元素,显然YES。
如果以上都不成立,显然NO。
上代码吧:
/*
ID: Loxilante
Time: 2020/08/07
Prog: B
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/stdc++.h>
#define rep(i, l, r) for(register int i = l; i < r; i++)
#define hrp(i, l, r) for(register int i = l; i <= r; i++)
#define rev(i, r, l) for(register int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn> inline tn next(void) { tn k; cin>>k; return k; }
const int U = 1e6+50;
int w[U], cnt[U];
multiset<int> four, two;
inline void inst(int e)
{
cnt[e]++;
if (cnt[e] == 4)
{
four.insert(e);
cnt[e] = 0;
two.erase(two.lower_bound(e));
}
else if (cnt[e] == 2) two.insert(e);
}
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int n = next<int>();
rep(i, 0, n) inst(next<int>());
int q = next<int>();
while(q--)
{
char sign;
int num;
cin>>sign>>num;
if (sign == '+') inst(num);
else
{
bool haveTwo = 0, haveFour = 0;
auto val = two.lower_bound(num);
if (*val == num) haveTwo = 1;
auto val2 = four.lower_bound(num);
if (*val2 == num) haveFour = 1;
if (haveTwo)
{
cnt[num]--;
if (cnt[num] == 1) two.erase(two.lower_bound(num));
}
else if (haveFour)
{
if (!cnt[num]) four.erase(four.lower_bound(num)), cnt[num] = 3, two.insert(num);
else cnt[num]--;
}
else cnt[num]--;
}
if (four.size() >= 2) cout<<"YES"<<endl;
else if (four.size() == 1 && two.size() >= 2) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
clock_t InputFinished = clock();
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
/*
inputCopy
6
1 1 1 2 1 1
6
+ 2
+ 1
- 1
+ 2
- 1
+ 2
outputCopy
NO
YES
NO
NO
NO
YES
*/
C:({color{red}{PiGeOnGuGuGu}})