zoukankan      html  css  js  c++  java
  • Codeforces Round# 305 (Div 1)

    [Codeforces 547A]

    #include <bits/stdc++.h>
    
    #define maxn 1000010
    using namespace std;
    typedef long long ll;
    bool vis[maxn];
    int md, h, a, x, y;
    
    int Go(int h, int x, int y){
    	memset(vis, 0, sizeof vis);
    	int cnt = 0;
    	while(true){
    		if(vis[h])
    			return -1;
    		vis[h] = 1;
    		h = (1ll * h * x + y) % md;
    		++ cnt;
    		if(h == a)
    			return cnt;
    	}
    }
    
    int main(){
    	scanf("%d", &md);
    	scanf("%d%d%d%d", &h, &a, &x, &y);
    	int a1 = Go(h, x, y), b1 = Go(a, x, y);
        scanf("%d%d%d%d", &h, &a, &x, &y);
        int a2 = Go(h, x, y), b2 = Go(a, x, y);
        if(a1 == -1 || a2 == -1)return puts("-1"), 0;
    	if(b1 == -1 && b2 == -1){
    		if(a1 == a2)printf("%d
    ", a1);
    		else printf("-1
    ");
    		return 0;
    	}
    	if(b1 != -1 && b2 != -1){
    		for(int i = 0; i <= md; i ++){
    			if(a1 + 1ll * b1 * i >= a2 && (a1 + 1ll * b1 * i - a2) % b2 == 0){
    				cout << a1 + 1ll * b1 * i << endl;
    				return 0;
    			}
    		}return puts("-1"), 0;
    	}
    	else{
    		if(b1 == -1)swap(a1, a2), swap(b1, b2);
    		if(a2 >= a1 && (a2 - a1) % b1 == 0)
    		    printf("%d
    ", a2);
    		else return puts("-1"), 0;
    	}
    	return 0;
    }
    

      

    [Codeforces 547B]

    题目大意: 就是给你一个序列,定义f(x)为(所有区间长度为x的最小值)的最大值,输出f(1)....f(n)

    n ≤ 2 * 10^5

    Sol:感觉用并查集就可以水。。

    #include <bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    
    int n;
    int a[maxn];
    
    int fa[maxn];
    int getfa(int x){return x == fa[x] ? x : fa[x] = getfa(fa[x]);}
    
    int h[maxn];
    
    bool cmp(int i, int j){
    	if(a[i] == a[j]) return i < j;
    	return a[i] < a[j];
    }
    
    int t;
    
    int size[maxn], f[maxn];
    inline void update(int x){
    	fa[x] = x, size[x] = 1;
    	if(t = getfa(x-1))fa[t] = x, size[x] += size[t];
    	if(t = getfa(x+1))fa[t] = x, size[x] += size[t];
    	f[size[x]] = max(f[size[x]], a[x]);
    	return;
    }
    
    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i ++)
    		scanf("%d", &a[i]), h[i] = i;
    	sort(h+1, h+1+n, cmp);
    
    	for(int i = n; i >= 1; i --)
    		update(h[i]);
    	for(int i = n; i >= 1; i --)
    	    f[i] = max(f[i+1], f[i]);
    	    
    	for(int i = 1; i <= n; i ++)
    	    printf("%d ", f[i]);
    	return 0;
    }
    

    [Codeforces 547C]

    题目大意:给定一个序列,初始为空,每次从序列中选出一个数字添加或删除,求gcd(Ai, Aj) = 1的有序数对(i, j)的个数。

    大爷题解传送门

    容斥原理。

    #include <bits/stdc++.h>
    #define maxn 1000010
    using namespace std;
    
    int N, Q;
    
    int A[maxn];
    
    vector<int> P[maxn];
    
    bool vis[maxn];
    int p[maxn], primes, mn[maxn];
    
    void prepare(){
    	mn[1] = 1;
    	int N = 500000;
    	for(int i = 2; i <= N; i ++){
    		if(!vis[i]){
    			p[primes ++] = i;
    			mn[i] = i;
    		}
    		for(int j = 0; j < primes; j ++){
    			if(1ll * i * p[j] > N)break;
    			vis[i * p[j]] = true;
    			if(i % p[j] == 0){mn[i * p[j]] = p[j];break;}
    			mn[i * p[j]] = mn[i];
    		}
    	}
    }
    
    void FJ(int Id, int A){
    	while(A != 1){
    		int now = mn[A];
    		while(A % now == 0)
    		    A /= now;
    		P[Id].push_back(now);
    	}
    }
    
    long long ans;
    
    int Bits[100], cnt[maxn];
    
    void update(int Id, int val){
    	int n = P[Id].size(), S = (1 << n) - 1;
    	for(int i = 0; i <= S; i ++){
            long long LCM = 1;
    		for(int j = 0; j < n; j ++)
    			if(i >> j & 1)
    				LCM = LCM * P[Id][j];
    		cnt[LCM] += val;
    	}
    }
    
    int QAQ(int S, int now){
        int n = P[now].size();
        long long ret = 0, LCM = 1;
    	for(int i = 0; i < n; i ++)
    		if(S >> i & 1)
    			LCM = LCM * P[now][i];
    	return cnt[LCM];
    }
    
    long long work(int now){
    	int n = P[now].size();
    	int S = (1 << n) - 1;
    	long long ret = 0;
    	for(int i = 0; i <= S; i ++)
            if(Bits[i] & 1)ret -= QAQ(i, now);
            else ret += QAQ(i, now);
    	return ret;
    }
    
    void solve(int Id){
    	if(vis[Id])update(Id, -1), ans -= work(Id);
    	else ans += work(Id), update(Id, 1);
    	vis[Id] ^= 1;
    }
    
    int main(){
    	prepare();
    	for(int i = 1; i < 1<<6; i ++)
    	    Bits[i] = __builtin_popcount(i);
    	scanf("%d%d", &N, &Q);
    	for(int i = 1; i <= N; i ++)
    	    scanf("%d", &A[i]);
    	for(int i = 1; i <= N; i ++)
    		FJ(i, A[i]);
    	memset(vis, 0, sizeof vis);
    	int Id;
    	for(int i = 1; i <= Q; i ++){
    		scanf("%d", &Id);
    		solve(Id);
    		printf("%I64d
    ", ans);
    	}
    	return 0;
    }
    

      

    [Codeforces 547D]

    题目大意:平面上有n个点,你需要给他们一一染色,可以染'b'(blue)或'r'(red),要求每一行和每一列所染色的(红色-蓝色)数目的绝对值<=1,输出染色方案。

    n ≤ 2 * 10^5

    QAQ虽然说一看就知道是网络流但是数据范围也是吓我一跳QAQ

    然而YY半天建图无果。。

    首先行和列示要看成点的,给的每一个点(x, y)看成一条边无疑,容量为1

    然后广告犇提出了限流思想:既然每行或每列不能相差超过1,那么就可以从源点->每一行连接容量为(cntx[i] / 2)的边,这样红蓝就一定符合条件了!(其中cntx[i]表示第i行有多少个点),从每一列连向汇点同理QAQ

    但是这样输出的方案可能还不够,有一些点仍然没有确定怎么办?(假如某一行某一列的点的个数为奇数。。)

    然后就弃疗了

    orz了一下神犇的题解(虽然说并不知道神犇是谁,但是网络流竟然可以过QAQ)

    先把行列离散化一下QAQ,然后如上建边,然后跑一边最大流,然后如果有多出来的就再添加一条容量为1的边,再跑一遍最大流。最后如果割掉了(edge[i<<1])说明此点和S相连,否则和T相连。

    某犇:我快YY出正解了

    主要程序:(网络流就不写了QAQ)

    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i ++)
    	    scanf("%d%d", &x[i], &y[i]);
        for(int i = 1; i <= n; i ++)
            ++ cx[x[i]], ++ cy[y[i]];
    	int id = 0;
    	for(int i = 1; i <= 200000; i ++)
    		if(cx[i])Idx[i] = ++ id;
        for(int i = 1; i <= 200000; i ++)
    		if(cy[i])Idy[i] = ++ id;
    	T = id + 1;
    	for(int i = 1; i <= n; i ++)
    	    add(Idx[x[i]], Idy[y[i]], 1);
    	for(int i = 1; i <= 200000; i ++)
    		if(cx[i] > 1) add(S, Idx[i], cx[i] >> 1);
        for(int i = 1; i <= 200000; i ++)
    		if(cy[i] > 1) add(Idy[i], T, cy[i] >> 1);
    	
    	Dinic();
    	for(int i = 1; i <= 200000; i ++)
    	    if(cx[i] & 1) add(S, Idx[i], 1);
        for(int i = 1; i <= 200000; i ++)
    	    if(cy[i] & 1) add(Idy[i], T, 1);
    	Dinic();
    	for(int i = 1; i <= n; i ++)
    	    if(!edge[i<<1].w)
    			putchar('b');
    		else putchar('r');
    	puts("");
    	return 0;
    }
    

    [Codeforces 547E]

    大爷题解传送门

    给出一大堆字符串,每次询问第k个串在第l~r的串中作为子串出现了多少次

    简述:AC自动机(failtree)的dfs序做可持久化。

    #include <bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    
    int n, m;
    
    char str[maxn];
    
    int tr[maxn][26], root, smz;
    
    int pos[maxn];
    
    struct Edge{
    	int to, nxt;
    }edge[maxn];
    int h[maxn], cnt;
    void add(int u, int v){
    	cnt ++;
    	edge[cnt].to = v;
    	edge[cnt].nxt = h[u];
    	h[u] = cnt;
    }
    
    
    void init(){
    	memset(tr, -1, sizeof tr);
    	root = smz = 0;
    }
    
    void Insert(int Id){
    	int N = strlen(str+1), now = root;
    	for(int i = 1; i <= N; i ++){
    		int c = str[i] - 'a';
    		if(tr[now][c] == -1)tr[now][c] = ++ smz;
    		now = tr[now][c];
    	}
    	pos[Id] = now;
    }
    
    queue<int> Q;
    
    int fa[maxn], fail[maxn];
    void buildfail(){
    	for(int i = 0; i < 26; i ++)
    	    if(tr[root][i] == -1) tr[root][i] = root;
    	    else fail[tr[root][i]] = root, Q.push(tr[root][i]), fa[tr[root][i]] = root;
    	while(!Q.empty()){
    		int u = Q.front(); Q.pop();
    		for(int i = 0; i < 26; i ++){
    			if(tr[u][i] == -1)tr[u][i] = tr[fail[u]][i];
    			else fail[tr[u][i]] = tr[fail[u]][i], Q.push(tr[u][i]), fa[tr[u][i]] = u;
    		}
    	}
    	for(int i = 1; i <= smz; i ++)
    	    add(fail[i], i);
    }
    
    int In[maxn], Out[maxn], dfs_clock;
    
    void dfs(int u){
    	In[u] = ++ dfs_clock;
    	for(int i = h[u]; i; i = edge[i].nxt)
    		dfs(edge[i].to);
    	Out[u] = dfs_clock;
    }
    
    #define M 10000010
    int T[maxn], L[M], R[M], val[M];
    
    int size;
    
    int build(int l, int r){
    	if(l > r) return 0;
    	int now = ++ size;
    	int mid = l + r >> 1;
    	L[now] = build(l, mid - 1);
    	R[now] = build(mid + 1, r);
    	return now;
    }
    
    int update(int rt, int pos, int l, int r){
    	int mid = l + r >> 1, now = ++ size;
    	L[now] = L[rt], R[now] = R[rt], val[now] = val[rt] + 1;
    	if(l == r) return now;
    	if(pos <= mid)L[now] = update(L[rt], pos, l, mid);
    	else R[now] = update(R[rt], pos, mid + 1, r);
    	return now;
    }
    
    int ask(int rt, int al, int ar, int l, int r){
    	if(al == l && ar == r)return val[rt];
    	int mid = l + r >> 1;
    	if(ar <= mid)return ask(L[rt], al, ar, l, mid);
    	if(al > mid) return ask(R[rt], al, ar, mid + 1, r);
    	return ask(L[rt], al, mid, l, mid) + ask(R[rt], mid + 1, ar, mid + 1, r);
    }
    
    int main(){
    	init();
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; i ++)
    		scanf("%s", str+1), Insert(i);
    	buildfail();
    	dfs(root);
    	T[0] = build(1, dfs_clock);
    	for(int i = 1; i <= n; i ++){
    		T[i] = T[i-1];
    		for(int j = pos[i]; j; j = fa[j])
    			T[i] = update(T[i], In[j], 1, dfs_clock);
    	}
    
    	int l, r, k;
    	for(int i = 1; i <= m; i ++){
    		scanf("%d%d%d", &l, &r, &k); l --;
    		printf("%d
    ", ask(T[r], In[pos[k]], Out[pos[k]], 1, dfs_clock) - ask(T[l], In[pos[k]], Out[pos[k]], 1, dfs_clock));
    	}
    	return 0;
    }
    
    
    /*
    5 5
    a
    ab
    abab
    ababab
    b
    1 5 1
    3 5 1
    1 5 2
    1 5 3
    1 4 5
    */
    

      

    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    笔记1
    笔记2
    笔记3
    两个多线程的交替打印
    三个多线程的交替打印
    内部类
    基本反射了解
    键盘监听事件KeyListener
    焦点监听事件FocusListener
    文本框JTextField,密码框JPasswordField
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5349825.html
Copyright © 2011-2022 走看看