Educational Codeforces Round 78

题目链接


A. Shuffle Hashing

  开场即读加题,全称心态爆炸,上来看了看,签到题,哈希?然后再读了读,尺取吧,过了TEST……然后交,WA2,emmm???然后魔改一下,会不会尺取的时候出了什么问题?魔改,继续……WA2???时间过去了半小时,第一次敲那么久的A…… ,开B,然后回来再写了A(91分钟才读明白题…… )

  结果,题目竟然是可以移动位置,但是字母的数目是不会变的,那么根本就不需要尺取,直接暴力找,暴力判断即可……读了假题,就说A为什么那么难……

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#define _ABS(x, y) ( x > y ? (x - y) : (y - x) )
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e2 + 7;
int N, num[30], cpy[30];
char s[maxN], c[maxN];
inline bool check()
{
    for(int i=0; i<26; i++) if(cpy[i]) return false;
    return true;
}
int main()
{
    int T; scanf("%d", &T);
    while(T--)
    {
        scanf("%s", s);
        scanf("%s", c);
        memset(num, 0, sizeof(num));
        int len_1 = (int)strlen(s), len_2 = (int)strlen(c);
        for(int i=0; i<len_1; i++)
        {
            num[s[i] - 'a']++;
        }
        bool ok = false;
        for(int i=0; i<=len_2 - len_1; i++)
        {
            for(int k=0; k<26; k++) cpy[k] = num[k];
            for(int j=i; j<len_2; j++)
            {
                cpy[c[j] - 'a']--;
                if(cpy[c[j] - 'a'] < 0) break;
                if(check())
                {
                    ok = true;
                    break;
                }
            }
            if(ok) break;
        }
        printf(ok ? "YES\n" : "NO\n");
    }
    return 0;
}

 


B. A and B

  这题花了五分钟签到。

  不过就是补差的过程,我们先假设差值是det,然后呢,我们就想办法填上这个差值,使得它们又同时到达一个统一标准,所以列写方程:

det + 2 * x = \frac{(n + 1) * n}{2}

也就是说

2 * det + 4 * x = (n + 1) * n

然后,我们现在就是想知道操作数n的求解。

现在det是已知数,x肯定要找最小,所以把首先满足n * (n + 1)的所有数打表预处理出来,然后呢,我们找连续的两个数,一定有一个是满足条件的,所以直接找即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define _ABS(x, y) ( x > y ? (x - y) : (y - x) )
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int _UP = 1e5 + 7;
ll a, b, det;
int tot;
ll tab[_UP];
int main()
{
    int T; scanf("%d", &T);
    for(ll i = 1LL; i < _UP; i++)
    {
        tab[i] = i * (i + 1LL);
    }
    while(T--)
    {
        scanf("%lld%lld", &a, &b);
        det = abs(a - b);
        if(!det) { printf("0\n"); continue; }
        det <<= 1;
        int id = (int)(lower_bound(tab + 1, tab + 100001, det) - tab);
        while((tab[id] - det) % 4)
        {
            id++;
        }
        printf("%lld\n", (ll)sqrt(tab[id]));
    }
    return 0;
}

 


C. Berry Jam

  由于直接开了m2快速链接,我看不到最后一个蓝莓酱的图片,一直懵逼了一会,回去写了A,读了两遍题,最后半小时A,然后呢,找到了些许感觉,在看C,把图片单独提出来看,哦豁!直接枚举两个端点啊!可以知道我们可以固定一个端点,然后在另一个端点去看,同时不要忘记,如果单边端点已经满足条件,需要即时更新答案。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define _ABS(x, y) ( x > y ? (x - y) : (y - x) )
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e5 + 7;
int N, a[maxN], b[maxN];
unordered_map<int, int> A;
int main()
{
    int T; scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &N);
        for(int i=1; i<=N; i++) scanf("%d", &a[i]);
        for(int i=N; i>=1; i--) scanf("%d", &b[i]);
        A.clear();
        int now = 0;
        int ans = 0;
        for(int i=1; i<=N; i++)
        {
            if(a[i] == 1) now--;
            else now++;
            A[now] = i;
            if(!now) ans = max(ans, i);
        }
        now = 0;
        for(int i=1; i<=N; i++)
        {
            if(b[i] == 1) now++;
            else now--;
            if(A[now]) ans = max(ans, i + A[now]);
            if(!now) ans = max(ans, i);
        }
        printf("%d\n", N * 2 - ans);
    }
    return 0;
}

 


D. Segment Tree

  比赛的时候没时间了,想到了正解,最后读完题还剩5分钟了呜呜呜…… 

  我们可以按照以往的思路,固定一维,然后去看另一维,同时,题目中似乎隐含的说了,不会有任意端点重合,也就是输入的l、r永远不会有相同的值出现的情况(尝试hack失败)。

  然后,首先按照一维排序,我这里按照r端点升序排列。那么,我们现在保证了放进去的点都是按照r端点升序的了,然后我们按照l端点放入,到r端点时候弹出这样的一个差分的思想来解决。

  我们按照l端点放入,并且放入的时候,我们找所有的r比l大的,并且他的对应的r还要比目前放入的r要小的,这里就可以维护出来了,因为r是单调的啊。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define _ABS(x, y) ( x > y ? (x - y) : (y - x) )
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 5e5 + 7;
int N, root[maxN];
int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
struct node
{
    int id, l, r;
    node(int a=0, int b=0, int c=0):id(a), l(b), r(c) {}
    friend bool operator < (node e1, node e2) { return e1.r < e2.r; }
};
multiset<node> st;
vector<node> add[maxN << 1], del[maxN << 1];
inline void init()
{
    for(int i=1; i<=N; i++) root[i] = i;
}
int main()
{
    scanf("%d", &N);
    init();
    int Beg = INF, End = 0;
    for(int i=1, l, r; i<=N; i++)
    {
        scanf("%d%d", &l, &r);
        add[l].push_back(node(i, l, r));
        del[r].push_back(node(i, l, r));
        Beg = min(Beg, l); End = max(End, r);
    }
    bool flag = true; int line = 0;
    for(int i = Beg; i <= End; i++)
    {
        for(node it : del[i])
        {
            st.erase(it);
        }
        for(node it : add[i])
        {
            multiset<node>::iterator pos = st.lower_bound(node(0, it.l, it.l));
            while(pos != st.end() && pos->r < it.r)
            {
                int u = pos->id, v = it.id;
                u = fid(u); v = fid(v);
                if(u != v)
                {
                    line++;
                    root[u] = v;
                }
                else { flag = false; break; }
                pos++;
            }
        }
        for(node it : add[i]) st.insert(it);
    }
    if(flag && line == N - 1) printf("YES\n");
    else printf("NO\n");
    return 0;
}

 


E. Tests for problem D

  简单的说一下这道题的题意,就是把D题反过来,现在我们知道这棵树,让我们构造出线段来,满足D题条件,SPJ。

  那么,简单构造一下,就是包含的关系了,譬如说样例一:

我们总长是1——12

现在我们给根结点赋值的是9——12,因为10和11分别指代了它的两个直接儿子的开始点位置,然后我们继续这样构造即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define _ABS(x, y) ( x > y ? (x - y) : (y - x) )
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 5e5 + 7;
int N, head[maxN], cnt;
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN << 1];
inline void addEddge(int u, int v)
{
    edge[cnt] = Eddge(head[u], v);
    head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
int siz[maxN], fa[maxN], dir[maxN]; //dir是直接和u相连的点的数量
void pre_dfs(int u, int father)
{
    siz[u] = 1; fa[u] = father; dir[u] = 0;
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == father) continue;
        pre_dfs(v, u);
        dir[u] ++;
        siz[u] += siz[v];
    }
}
struct node
{
    int l, r;
    node(int a=0, int b=0):l(a), r(b) {}
    inline void Out() { printf("%d %d\n", l, r); }
}ans[maxN];
int L;
void dfs(int u, int fail)
{
    ans[u] = node(L - dir[u], fail);
    L = L - 1 - dir[u];
    int Beg = L + 2;
    for(int i=head[u], v; ~i; i=edge[i].nex)
    {
        v = edge[i].to;
        if(v == fa[u]) continue;
        dfs(v, Beg++);
    }
}
inline void init()
{
    cnt = 0;
    for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
    scanf("%d", &N);
    init();
    for(int i=1, u, v; i<N; i++)
    {
        scanf("%d%d", &u, &v);
        _add(u, v);
    }
    pre_dfs(1, 0);
    L = (N << 1) - 1;
    dfs(1, N << 1);
    for(int i=1; i<=N; i++) ans[i].Out();
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值