• 牛客小白月赛12


    比赛传送门

    这真的是小白月赛么……
    说好的“题目难度在(CF; DIV2;A)~(C)”呢?
    (D,E)两题为数学题,所以不想整(并没有歧视数学的意思)

    A.华华听月月唱歌

    贪心区间覆盖裸题,但细节需要注意

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') { 
            if(c == '-') f = -1;
            c = getchar(); 
        } 
        while(c >= '0' && c <= '9')
          k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    struct zzz {
    	int f, t;
    }xd[100010];
    bool cmp(zzz x, zzz y) {
        if(x.f != y.f)  return x.f < y.f;
        else return x.t > y.t;
    }
    int main() {
        int n = read(), tot = read();
    	for(int i = 1; i <= tot; ++i)
    	  xd[i].f = read(), xd[i].t = read();
        sort(xd+1, xd+tot+1, cmp);
    	int t = 0, ans = 0, pos = 1;
    	while(t < n) {
    		++ans;
    		int flag = t;
    		for(; xd[pos].f <= flag+1 && pos <= tot; ++pos)
    		  t = max(t, xd[pos].t);
    		if(t == flag && flag < n) {
    			cout << -1; exit(0);
    		}
    	}
    	cout << ans;
    	return 0;
    }
    

    B.华华教月月做数学

    快速幂+龟速乘

    #include<iostream>
    #include<cstdio>
    #define LL long long
    using namespace std;
    LL mul(LL b, LL p, LL k) {
        LL ans = 0;
        for(; p; p >>= 1) {
            if(p & 1)
              ans = (ans + b) % k;
            b = (b + b) % k;
        }
        return ans % k;
    }
    LL pow(LL b, LL p, LL k) {
        LL ans = 1;
        for(; p; p >>= 1) {
            if(p & 1)
              ans = mul(ans, b, k);
            b = mul(b, b, k);
        }
        return ans % k;
    }
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
          k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    int main() {
        int t = read();
        while(t--) {
            LL b = read(), p = read(), k = read();
            cout << pow(b, p, k) << endl;
        }
        return 0;
    }
    

    还有好写的Python

    t = input()
    for i in range(0, (int)(t)) :
    	s = input().split()
    	print(pow(int(s[0]), int(s[1]) , int(s[2])))
    

    E.华华给月月准备礼物

    二分答案

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') { 
            if(c == '-') f = -1;
            c = getchar(); 
        } 
        while(c >= '0' && c <= '9')
          k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    int a[200010], l = 1, r;
    int n, m;
    bool judge(int x) {
    	int ans = 0;
    	for(int i = 1; i <= n; ++i)
    	  ans += a[i]/x;
    	if(ans < m) return 0;
    	else return 1;
    }
    int main() {
        n = read(), m = read();
    	for(int i = 1; i <= n; ++i)
    	  a[i] = read(), r = max(a[i], r)+1;
    	while(l < r) {
    		int mid = (l+r) >> 1;
    		if(judge(mid)) l = mid+1;
    		else r = mid;
    	}
    	cout << l-1;
    	return 0;
    }
    

    F.华华开始学信息学

    很神仙的一道题,之前从来没见过这种思想

    如果暴力使用树状数组来维护,每次修改的时间复杂度为(O(frac{n}{x}log n))(x)为模数,查询时间复杂度为(O(n log n))

    显然可以发现当(x)越大,使用树状数组维护的效率越高,而(x)较小的时候使用树状数组是十分不理智的,此时可以使用一个桶来维护,令tong[i]表示模数为(i)时加了多少

    (x)为多少时用树状数组或是桶呢?
    显然当(x)(sqrt{n})时效率最高,修改时为(O(sqrt{n} log n)),查询为(O(sqrt{n}+ log n))

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <cmath>
    #define LL long long
    #define lb (i & (-i))
    using namespace std;
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
          k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    LL tree[100010 << 1], tong[100010];
    int n, m;
    void add(int pos, LL x) {
        for(int i = pos; i <= n; i += lb) tree[i] += x;
    }
    LL sum(int pos) {
        LL ans = 0;
        for(int i = pos; i; i -= lb) ans += tree[i];
        return ans;
    }
    int main() {
        n = read(), m = read(); int maxx = sqrt(n);
        for(int i = 1; i <= m; ++i) {
            LL opt = read(), x = read(), y = read();
            if(opt == 1) {
                if(x > maxx)
                  for(int j = x; j <= n; j += x) add(j, y);
                else tong[x] += y;
            }
            else {
                LL ans = sum(y) - sum(x-1);
                for(int j = 1; j <= maxx; ++j) ans += (y/j - (x-1)/j) * tong[j];
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
    

    G.华华对月月的忠诚

    虽然(N)很大,但答案和(N)没有关系,直接求(a,b)(gcd)即可

    H.华华和月月种树

    一开始以为是树剖,事实证明我想多了(数据结构的受害者)

    动态开点不好维护,我们可以离线操作
    先在输入的时候跟着(1)操作加点,建出最终的树,然后求此树的(DFS)序和每个点的子树大小
    这样就把(2,3)操作变为了区间加和单点查询,可以用查分树状数组来维护
    而对于(1)操作,加入新的点时要将这个点上的信息清空

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #define lb (i & (-i))
    #define LL long long
    using namespace std;
    int read() {
    	int k = 0; char c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9')
    	  k = k * 10 + c - 48, c = getchar();
    	return k;
    }
    struct zzz {
    	int t, nex;
    }e[100010 << 1]; int head[100010], tot;
    void add(int x, int y) {
    	e[++tot].t = y;
    	e[tot].nex = head[x];
    	head[x] = tot;
    }
    struct hhh {
    	int opt, x, y;
    }que[400010]; int cnt;
    int siz[100010], p[100010], num = 1;
    void dfs(int pos, int fa) {
    	p[pos] = num;
    	for(int i = head[pos]; i; i = e[i].nex)
    	  if(e[i].t != fa)
    		++num, dfs(e[i].t, pos), siz[pos] += siz[e[i].t];
    	siz[pos] += 1;
    }
    int m, n;
    LL tree[100010 << 1];
    void del(int x) {
    	for(int i = x; i <= n; i += lb) tree[i] = 0;
    }
    void update(int x, int k) {
    	for(int i = x; i <= n; i += lb) tree[i] += k;
    }
    LL sum(int x) {
    	LL ans = 0;
    	for(int i = x; i; i -= lb) ans += tree[i];
    	return ans;
    }
    int main() {
    	m = read(), n = 1;
    	for(int i = 1; i <= m; ++i) {
    		int x = read(); que[++cnt].opt = x;
    		if(x == 1) {
    			int y = read()+1; que[cnt].x = y;
    			add(++n, y), add(y, n);
    		}
    		if(x == 2)
    		  que[cnt].x = read()+1, que[cnt].y = read();
    		if(x == 3)
    		  que[cnt].x = read()+1;
    	}
    	dfs(1, 0); num = 1;	
    	for(int i = 1; i <= cnt; ++i) {
    		if(que[i].opt == 1) {
    			int pos = p[++num];
    			int k = sum(pos); update(pos, -k), update(pos+1, k);
    		}
    		if(que[i].opt == 2) {
    			int pos = que[i].x, k = que[i].y;
    			update(p[pos], k); update(p[pos]+siz[pos], -k);
    		}
    		if(que[i].opt == 3) {
    			int pos = que[i].x;
    			printf("%lld
    ", sum(p[pos]));
    		}
    	}
    	return 0;
    }
    

    I.华华和月月逛公园

    (Tarjan)求割边板子题

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    struct zzz {
    	int t, nex;
    }e[300010 << 1];
    int head[100010], tot;
    void add(int x, int y) {
    	e[++tot].t = y;
    	e[tot].nex = head[x];
    	head[x] = tot;
    }
    int dfn[100010], low[100010], deth, ans;
    void tarjan(int pos, int fa) {
    	low[pos] = dfn[pos] = ++deth;
    	for(int i = head[pos]; i; i = e[i].nex) {
    		int to = e[i].t;
    		if(!dfn[to]) {
    			tarjan(to, pos);
    			low[pos] = min(low[pos], low[to]);
    			if(low[to] > dfn[pos]) ++ans;
    		}
    		else if(to != fa)
    		  low[pos] = min(low[pos], dfn[to]);
    	}
    }
    int read() {
    	int k = 0; char c = getchar();
    	for (; c < '0' || c > '9';) c = getchar();
    	for (; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - 48;
    	return k;
    }
    int main() {
    	int n = read(), m = read();
    	for(int i = 1; i <= m; ++i) {
    		int x = read(), y = read();
    		add(x, y), add(y, x);
    	}
    	for(int i = 1; i <= n; ++i)
    	  if(!dfn[i]) tarjan(i, i);
    	cout << m - ans;
    	return 0;
    }
    

    J.月月查华华的手机

    学了一个新东西:“序列自动机”
    对于母串每一位都记一下下一次出现某个字符的位置。匹配的时候从第零位(虚根)开始,如果能一直匹配下去就是(Yes),否则就是(No)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #define LL long long
    #define lb (i & (-i))
    using namespace std;
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
          k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    int e[1000010][26];
    char A[1000010];
    int main() {
    	scanf("%s", A+1); int len = strlen(A+1);
    	for(int i = len-1; i >= 0; --i) {
    		for(int j = 0; j < 26; ++j) e[i][j] = e[i+1][j];
    		e[i][A[i+1]-'a'] = i+1;
    	}
    	int m = read();
        for(int i = 1; i <= m; ++i) {
    		scanf("%s", A+1);
    		int nex = 0, pos = 1, len = strlen(A+1);
    		while(e[nex][A[pos]-'a'] && pos <= len+1)
    		  nex = e[nex][A[pos]-'a'], ++pos;
    		if(pos <= len) printf("No
    ");
    		else printf("Yes
    ");
    	}
    
        return 0;
    }
    
  • 相关阅读:
    CSS学习笔记
    metadata的深入
    [极客大挑战 2019]BabySQL
    [极客大挑战 2019]LoveSQL
    [强网杯 2019]随便注
    [SUCTF 2019]CheckIn 1
    [ZJCTF 2019]NiZhuanSiWei 1
    [BJDCTF2020]Easy MD5
    [极客大挑战 2019]BuyFlag
    [ACTF2020 新生赛]BackupFile
  • 原文地址:https://www.cnblogs.com/morslin/p/11855207.html
Copyright © 2020-2023  润新知