zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 78 (Rated for Div. 2) 题解

    Shuffle Hashing

    [Time Limit: 2 squad Memory Limit: 256 MB ]

    处理出 (s_1) 中各个字符出现的次数,然后双指针维护 (s_2) 中每一段长度为 (len(s_1)) 的串中字符出现的次数,如果存在某一段和 (s_1) 的字符次数相同,则是答案。

    view
    #include <map>
    #include <set>
    #include <list>
    #include <tuple>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pb         push_back
    #define  pii        pair<int, int>
    #define  INOPEN     freopen("in.txt", "r", stdin)
    #define  OUTOPEN    freopen("out.txt", "w", stdout)
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 1e2 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m, k;
    int cas, tol, T;
    
    int cnt[26];
    char s1[maxn], s2[maxn];
    
    bool ok() {
    	for(int i=0; i<26; i++)	if(cnt[i])	return 0;
    	return 1;
    }
    
    int main() {
    	scanf("%d", &T);
    	while(T--) {
    		mes(cnt, 0);
    		scanf("%s%s", s1+1, s2+1);
    		n = strlen(s1+1), m = strlen(s2+1);
    		if(n>m) {
    			puts("NO");
    			continue;
    		}
    		for(int i=1; i<=n; i++)	cnt[s1[i]-'a']++;
    		for(int i=1; i<=n; i++)	cnt[s2[i]-'a']--;
    		bool f = 0;
    		for(int i=n; i<=m; i++) {
    			if(ok())	f = 1;
    			if(i==m)	break;
    			cnt[s2[i+1]-'a']--;
    			cnt[s2[i-n+1]-'a']++;
    		}
    		puts(f ? "YES" : "NO");
    	}
    	return 0;
    }
    

    A and B

    [Time Limit: 1 squad Memory Limit: 256 MB ]

    说出来你可能不信,强行 (oeis) 过了。

    view
    #include <map>
    #include <set>
    #include <list>
    #include <tuple>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pb         push_back
    #define  pii        pair<int, int>
    #define  INOPEN     freopen("in.txt", "r", stdin)
    #define  OUTOPEN    freopen("out.txt", "w", stdout)
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 1e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    ll n, m;
    int cas, tol, T;
    
    int main() {
    	scanf("%d", &T);
    	while(T--) {
    		ll a, b;
    		scanf("%lld%lld", &a, &b);
    		n = abs(a-b);
    		ll k=0;
    		for(; ; k++) {
    			if(k*(k+1)/2 <= n && n<(k+1)*(k+2)/2)	break;
    		}
    		ll tk = k*(k+1)/2;
    		ll ans;
    		if(n == tk)	ans = k;
    		else {
    			if(k%2 == 1) {
    				if((n-tk)%2==1)	ans = k+2;
    				else	ans = k+1;
    			} else {
    				if((n-tk)%2==1)	ans = k+1;
    				else	ans = k+3;
    			}
    		}
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    Berry Jam

    [Time Limit: 2 squad Memory Limit: 256 MB ]

    预处理后半段中 (1)(2) 多吃 (x) 瓶所需要的最少步数,然后枚举前半段中吃到第 (i) 瓶处,(1) 还需要比 (2) 多吃 (y) 瓶,然后在后半段预处理中找答案。

    view
    #include <map>
    #include <set>
    #include <list>
    #include <tuple>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pb         push_back
    #define  pii        pair<int, int>
    #define  INOPEN     freopen("in.txt", "r", stdin)
    #define  OUTOPEN    freopen("out.txt", "w", stdout)
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 2e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m;
    int cas, tol, T;
    
    int a[maxn];
    unordered_map<int, int> mp;
    
    int main() {
    	scanf("%d", &T);
    	while(T--) {
    		mp.clear();
    		scanf("%d", &n);
    		int y = 0;
    		for(int i=1; i<=n+n; i++) {
    			scanf("%d", &a[i]);
    			y += a[i]==1 ? 1:-1;
    		}
    		if(y == 0) {
    			printf("0
    ");
    			continue;
    		}
    		mp[0] = 0;
    		for(int i=n+1, x=0; i<=n+n; i++) {
    			x += a[i]==1 ? 1:-1;
    			if(!mp.count(x))	mp[x] = i-n;
    		}
    //		for(auto t : mp)	printf("%d %d
    ", t.fi, t.se);
    		int ans = inf;
    		for(int i=n; i>=0; i--) {
    			if(mp.count(y))	
    				ans = min(ans, n-i+mp[y]);
    			if(!i)	break;
    			y -= a[i]==1 ? 1:-1;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    Segment Tree

    [Time Limit: 2 squad Memory Limit: 256 MB ]

    把线段先按 (l) 在按 (r) 排序,然后枚举第 (i) 条线段,判断它可以和哪些线段连边。

    可以发现,在枚举第 (i) 条线段时,前 (i-1) 条线段的 (l) 一定都是比我的 (l) 小的,所以我其实是需要找到前 (i-1) 条线段中,找到所有满足 (p[i].l leq p[j].r leq p[i].r) 的所有 (j)

    这一段区间是连续的,所以我们可以维护一个 (set)(pair),用来存放前 (i-1) 条边的 (r) 位置和编号。然后用 (set) 的二分来快速找到所有的 (j)

    又因为想要形成一棵树,这也就意味着最多只会添加 (n-1) 条边,那么整体复杂度就不会太大。

    view
    #include <map>
    #include <set>
    #include <list>
    #include <tuple>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  l          first
    #define  r          second
    #define  pb         push_back
    #define  pii        pair<int, int>
    #define  INOPEN     freopen("in.txt", "r", stdin)
    #define  OUTOPEN    freopen("out.txt", "w", stdout)
     
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 5e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m;
    int cas, tol, T;
    
    int fa[maxn];
    pii p[maxn];
    set<pii> st;
    
    int find(int x) {
    	return fa[x]==x ? x : fa[x]=find(fa[x]);
    }
    
    bool bind(int x, int y) {
    	x = find(x), y = find(y);
    	if(x == y)	return 0;
    	fa[x] = y;
    	return 1;
    }
    
    int main() {
    	scanf("%d", &n);
    	for(int i=1; i<=n; i++) {
    		scanf("%d%d", &p[i].l, &p[i].r);
    		fa[i] = i;
    	}
    	sort(p+1, p+1+n);
    	st.clear();
    	int sz = 0, f = 1;
    	for(int i=1; i<=n; i++) {
    		auto pos = st.lower_bound({p[i].l, -1});
    		for(auto j = pos; j!=st.end(); j++) {
    			if((*j).l > p[i].r)	break;
    			sz++;
    			if(sz==n || !bind(i, (*j).r)) {
    				f = 0;
    				break;
    			}
    		}
    		if(!f)	break;
    		st.insert({p[i].r, i});
    	}
    	set<int> ans;
    	for(int i=1; i<=n; i++)	ans.insert(find(i));
    	puts(ans.size()==1&&f ? "YES" : "NO");
    	return 0;
    }
    

    Tests for problem D

    [Time Limit: 2 squad Memory Limit: 256 MB ]

    考虑模拟一下第一个样例,它的放置规则是先把 (1) 看成整棵树的根,那么可以先确定 (p[1].r = 2*n),然后它有两个直接儿子,所以我需要在 (r) 前面留两个空给这两个儿子放 (r) 用,现在已经没有直接儿子了,为了防止新的交叉出现,接下来我就放上自己的 (l),对于下面的儿子也是同理,可以递归处理。

    然后就是儿子的 (l) 问题了,由于 (1) 的各个儿子不能有交叉部分,也就意味着这些得是重合起来的,所以一开始放在最后的 (r),其对应的 (l) 就应该尽量小,所以我越早放在后面的儿子,应该越晚去 (dfs) 确定其 (l)

    为了防止数字重复被用到,可以用一个 (set) 来维护还可以用的数字。

    view
    #include <map>
    #include <set>
    #include <list>
    #include <tuple>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  l          first
    #define  r          second
    #define  pb         push_back
    #define  pii        pair<int, int>
    #define  INOPEN     freopen("in.txt", "r", stdin)
    #define  OUTOPEN    freopen("out.txt", "w", stdout)
     
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 5e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m;
    int cas, tol, T;
    
    set<int> st;
    pii p[maxn];
    vector<int> g[maxn];
    
    void dfs(int u, int fa) {
    	int len = g[u].size();
    	for(int i=0; i<len; i++) if(g[u][i] != fa) {
    		p[g[u][i]].r = *(--st.end());
    		st.erase((--st.end()));
    	}
    	p[u].l = *(--st.end());
    	st.erase((--st.end()));
    //	printf("p%d .l = %d .r = %d
    ", u, p[u].l, p[u].r);
    	for(int i=len-1; ~i; i--) if(g[u][i] != fa) {
    		dfs(g[u][i], u);
    	}
    }
    
    int main() {
    	scanf("%d", &n);
    	for(int i=2, u, v; i<=n; i++) {
    		scanf("%d%d", &u, &v);
    		g[u].pb(v), g[v].pb(u);
    	}
    	p[1].r = 2*n;
    	for(int i=1; i<2*n; i++)	st.insert(i);
    	dfs(1, 1);
    	for(int i=1; i<=n; i++)	printf("%d %d
    ", p[i].l, p[i].r);
    	return 0;
    }
    /*
    3
    1 2
    1 3
    */
    
  • 相关阅读:
    C++派生类中定义基类的虚函数时需注意的事项
    [wp7软件]wp7~~各种视频播放器下载大全! 集合贴~~~
    [wp7软件]wp7~~日历软件下载大全! 集合贴~~~
    [wp7软件]相机 画图 截屏 photo 集合 软件(三)
    [wp7软件]相机 画图 截屏 photo 集合 软件(二)
    [wp7软件]wp7~~天气查询软件下载大全! 集合贴~~~
    [wp7软件]相机 画图 截屏 photo 集合 软件(一)
    [wp7软件]wp7~~各种浏览器下载大全! 集合贴~~~
    [wp7软件]wp7~~各种音乐播放器下载大全! 集合贴~~~
    [wp7软件]相机 画图 截屏 photo 集合 软件(四)
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/12075688.html
Copyright © 2011-2022 走看看