zoukankan      html  css  js  c++  java
  • Codeforces Round #662 Div.2 (CF1392)

    有人说这场背景描述挺烂,不过我觉得还不错(

    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}})

  • 相关阅读:
    流行-Manifold学习理解与应用
    狠心奶奶自断亲情,28年后孙女拒绝相见:人有没有不原谅的权利?
    学术论文常用词汇总结(待更新)
    机动车驾驶(2)--- 老司机经验
    关于MySQL数据导出导入
    php5.6-lumen与php5.6-phalcon性能对比
    win7(64bit)+python3.5+pyinstaller3.2安装和测试
    WARNING: Can not get binary dependencies for file...
    一些不错的计算机书籍
    PHP扩展类ZipArchive实现压缩解压Zip文件和文件打包下载
  • 原文地址:https://www.cnblogs.com/Loxilante/p/CF1392.html
Copyright © 2011-2022 走看看