zoukankan      html  css  js  c++  java
  • Contest Hunter Round #70

    orz lydrainbowcat

    [Problem A]「艦これ市」70万幕后交易事件

    排序机器=-=。重要的是相同的处理。

    我们可以从小到大添加数字,然后维护一个位置的序列。每一种相等的数字都在一块。如果我们要添加一个新的数字,要把位置>它的数字全部弹出,而且要把小于它的数字(在队头)全部弹出,这样才能保证正确性和最优性。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    #define maxn 1000010
    
    int n, m, ans;
    
    int a[maxn];
    
    vector<int> b[maxn];
    
    int q[maxn];
    
    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i ++){
    		scanf("%d", &a[i]);
    		b[a[i]].push_back(i);
    		m = max(m, a[i]);
    	}
    	int l = 1, r = 0;
    	for(int i = 1; i <= m; i ++){
    		int N = b[i].size();
    		for(int j = N - 1; j >= 0; j --){
    			int k = b[i][j];
    			while(l <= r && q[r] > k){
    			    while(l <= r && a[q[l]] < a[q[r]])
    					l ++;
    				r --;
       			}
    			ans = max(ans, r - l + 1 + N - j);
    		}
    		for(int j = 0; j < b[i].size(); j ++)
    		    q[++ r] = b[i][j];
    	}
    	printf("%d
    ", n - ans);
    	return 0;
    }
    

    [Problem B]「NOIP市」神秘PY交易事件(前篇)  

    题目意思好长。。

    而且两个人同能力要相等的工资??

    暴力都写炸了。。QAQ。。

    bruteforce:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define maxn 100010
    using namespace std;
    
    struct Edge{
    	int to, next, dis;
    	Edge(int v = 0, int nxt = 0, int d = 0){
    		to = v, next = nxt, dis = d;
    	}
    }edge[maxn << 2];
    
    int h[maxn], cnt, n;
    void add(int u, int v, int d){
    	edge[++ cnt] = Edge(v, h[u], d); h[u] = cnt;
    }
    
    int dis[maxn];
    queue<int>Q;
    bool vis[maxn];
    void Spfa(){
    	int ans = 0;
    	for(int i = 1; i <= n; i ++)
    	    add(0, i, 1);
    	Q.push(0);
    	memset(dis, 0x80, sizeof dis);
    	dis[0] = 0;
    	while(!Q.empty()){
    		int u = Q.front(); Q.pop();
    		for(int i = h[u]; i; i = edge[i].next){
    			int v = edge[i].to;
    			if(dis[v] < dis[u] + edge[i].dis){
    				dis[v] = dis[u] + edge[i].dis;
    				if(vis[v] == false)
    				    vis[v] = true, Q.push(v);
    			}
    		}vis[u] = false;
    	}
    	for(int i = 1; i <= n; i ++)
    		ans += dis[i];
    
    	printf("%d
    ", ans);
    }
    
    int c[maxn];
    
    Edge G[maxn << 2];
    int H[maxn], CNT;
    void Ins(int u, int v){
    	CNT ++;
    	G[CNT].to = v;
    	G[CNT].next = H[u];
    	H[u] = CNT;
    }
    
    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i ++)
    	    scanf("%d", &c[i]);
    	int u, v, m;
    	scanf("%d", &m);
    	for(int i = 1; i <= m; i ++){
    		scanf("%d%d", &u, &v);
    		Ins(u, v); Ins(v, u);
    	}
    
    	for(int i = 1; i <= n; i ++){
    		for(int j = H[i]; j; j = G[j].next){
    			int v = G[j].to;
    			if(c[i] < c[v])
    			    add(i, v, 1);
    			if(c[i] == c[v])
    				add(i, v, 0), add(v, i, 0);
    			for(int k = H[i]; k; k = G[k].next){
    				int u = G[k].to;
    				if(c[v] < c[u])
    				    add(v, u, 1);
    				if(c[v] == c[u])
    				    add(v, u, 0), add(u, v, 0);
    			}
    		}
    	}
    	Spfa();
    	return 0;
    }
    

    然而正解是这样的。。对于相邻的人,如果能力值相同那么工资一定相同。这样工资相同的人可能会组成一些强连通分量,我们如果把这些scc缩掉就会形成一个DAG。(这个可以用并查集实现)。跑差分约束(最长路)或者拓扑排序都可。然后对于每一个点相邻的sort一遍,由于相邻的人的的能力值都不同,所以可以在相邻点之间连边即可(建边优化)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <stack>
    #define maxn 100010
    using namespace std;
    
    vector<int> G[maxn];
    
    int c[maxn];
    
    bool cmp(int i, int j){return c[i] < c[j];}
    
    struct Edge{
    	int to, next;
    	Edge(int v = 0, int nxt = 0){
    		to = v, next = nxt;
    	}
    }edge[maxn << 4];
    int h[maxn], cnt, n, In[maxn];
    void add(int u, int v){
    	edge[++ cnt] = Edge(v, h[u]);
    	h[u] = cnt;  ++ In[v];
    }
    
    int fa[maxn];
    int getfa(int x){return x == fa[x] ? x : fa[x] = getfa(fa[x]);}
    inline void Union(int x, int y){
    	x = getfa(x), y = getfa(y);
    	fa[x] = y;
    }
    
    stack<int> S;
    
    int ans[maxn], ct[maxn];
    
    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i ++)
    	    scanf("%d", &c[i]), fa[i] = i;
    	int u, v, m;
    	scanf("%d", &m);
    	for(int i = 1; i <= m; i ++){
    		scanf("%d%d", &u, &v);
    		G[u].push_back(v);
    		G[v].push_back(u);
    		if(c[u] == c[v])
    		    Union(u, v);
    	}
    
    	for(int i = 1; i <= n; i ++){
    		sort(G[i].begin(), G[i].end(), cmp);
    		for(int j = 1; j < G[i].size(); j ++)
    			if(c[G[i][j]] == c[G[i][j-1]])
    			    Union(G[i][j], G[i][j-1]);
    	}
    	
    	
    	for(int i = 1; i <= n; i ++){
    		for(int j = 0; j < G[i].size(); j ++)
    		    if(c[i] < c[G[i][j]])
    		        add(getfa(i), getfa(G[i][j]));
    		for(int j = 1; j < G[i].size(); j ++)
    		    if(getfa(G[i][j-1]) != getfa(G[i][j]))
    		        add(getfa(G[i][j-1]), getfa(G[i][j]));
    	}
    
    
    	for(int i = 1; i <= n; i ++)
    	    if(In[i] == 0 && getfa(i) == i)
    			S.push(i);
    
    	for(int i = 1; i <= n; i ++)
    	    ct[getfa(i)] ++, ans[i] = 1;
    	long long ret = 0;
    	while(!S.empty()){
    		int u = S.top(); S.pop();
    		ret += 1ll * ct[u] * ans[u];
    		for(int i = h[u]; i; i = edge[i].next){
    			int v = edge[i].to;
    			In[v] --;
    			ans[v] = max(ans[v], ans[u] + 1);
    			if(In[v] == 0) S.push(v);
    		}
    	}
    
    	printf("%lld
    ", ret);
    	return 0;
    }
    

      

    给时光以生命,而不是给生命以时光。
  • 相关阅读:
    C# 7.2 通过 in 和 readonly struct 减少方法值复制提高性能
    .net remoting 使用事件
    .net remoting 使用事件
    WPF 使用 SharpDX 在 D3DImage 显示
    PHP readlink() 函数
    PHP readfile() 函数
    PHP popen() 函数
    PHP pclose() 函数
    PHP pathinfo() 函数
    latin1字符集的数据转换为utf8字符集
  • 原文地址:https://www.cnblogs.com/Candyouth/p/5352762.html
Copyright © 2011-2022 走看看