【2017summer Day1】

srO GTY

A.刪除
del

數字出現的種數及個數
優先刪除重複出現的數字
也就是 查詢重複出現的數字的個數 即重複值
// 比如1 1 1 2 3 3 重複值爲3

如果重複值比k小?
從剩下的數字中繼續刪,同時答案減減減

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int n,k,num[MAXN];
int ans = 0,cnt = 0;

int main(){
    freopen("del.in","r",stdin);
    freopen("del.out","w",stdout);
    memset(num,0,sizeof(num));
    scanf("%d %d",&n,&k);
    for(int i = 1; i <= n; i ++) scanf("%d",&num[i]);
    sort(num + 1,num + n + 1);
    for(int i = 1; i <= n; i ++) {
        if(num[i] == num[i - 1]) cnt ++;
        else ans ++;
    }
    if(cnt >= k) printf("%d\n",ans);
    else{k -= cnt; ans -= k; printf("%d\n",ans);}
    return 0;
}

B.同花順
card

排序去重 // 去重!!!
對於每張牌 以它爲最後一張now 尋找可能的第一張last
存在now - last + 1 <= n
改的牌數最小

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int n,tot,ans = 1,lasts = 1;
struct edge{
    int hs,sz;
}e[MAXN];
edge l[MAXN];

bool cmp(edge a,edge b){
    if(a.hs == b.hs) return a.sz < b.sz;
    else return a.hs < b.hs;
}

int main(){
    freopen("card.in","r",stdin);
    freopen("card.out","w",stdout);
    scanf("%d",&tot);
    for(int i = 1; i <= tot; i ++)
        scanf("%d %d",&e[i].hs,&e[i].sz);
    sort(e + 1,e + tot + 1,cmp);
    for(int i = 1; i <= tot; i ++){
        if(e[i].sz == e[i - 1].sz && e[i].hs == e[i - 1].hs) continue; 
        n ++; l[n].sz = e[i].sz; l[n].hs = e[i].hs;
    }
//  n = unique(e + 1,e + 1 + tot) - e - 1;
    for(int i = 1; i <= n; i ++){
        if(i == 1) lasts = i;
        else if(l[i].hs != l[i - 1].hs) lasts = i;
        while(l[i].sz - l[lasts].sz + 1 > tot) lasts ++;  
        ans = max(ans,i - lasts + 1);
    }
    ans = tot - ans;
    printf("%d\n",ans);
    return 0;
}

C.等式
equ

兩種思路
1.灌水法+離散化
等式 == 建邊
從沒有標記的點開始遍歷所有它能經過的點
每次標記用不同的 比如第一次遍歷標記1 第二次遍歷標記2
如果兩個要求不同的點標記相同 就是式子們不能同時成立

2.並查集+離散化
等式 == 在同一集合
先把所有等式關係的點合併
最後檢驗不等式是否成立
如果兩個要求不同的點在同一集合中 就是式子們不能同時成立

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 300005;
int n,T,f[MAXN],t[MAXN],v[MAXN];
int lsh[MAXN],tot = 0;
bool flag = false;
int fa[MAXN];

void init(){
    memset(f,0,sizeof(f));
    memset(t,0,sizeof(t));
    memset(v,0,sizeof(v));
    memset(lsh,0,sizeof(lsh));
    for(int i = 1; i <= n * 2 + 1; i ++) fa[i] = i;
    tot = 0; flag = false;
    return;
}

int find(int x){
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

int where(int x){
    return lower_bound(lsh + 1,lsh + n + n + 1,x) - lsh;
}

void merge(int x,int y){
    x = find(x); y = find(y);
    fa[x] = y;
    return; 
}

bool same(int x,int y){
    return find(x) == find(y);
}

int main(){
    freopen("equ.in","r",stdin);
    freopen("equ.out","w",stdout);
    scanf("%d",&T);
    while(T --){
        scanf("%d",&n); init();
        for(int i = 1; i <= n; i ++){
            scanf("%d %d %d",&f[i],&t[i],&v[i]);
            tot ++;lsh[tot] = f[i];
            tot ++;lsh[tot] = t[i];
        }
        sort(lsh + 1,lsh + tot + 1);
        for(int i = 1; i <= n; i ++){
            if(flag) continue;
            int ff = where(f[i]);
            int tt = where(t[i]);
            if(v[i] == 1) merge(ff,tt);
    //      else if(v[i] == 0)  if(same(ff,tt)) flag = true;
            //先合併再檢驗 
            //對於所有式子同時成立  v == 0的情況不一定在末尾出現     
        }
        for(int i = 1;i <= n; i ++){
            int ff = where(f[i]);
            int tt = where(t[i]);
            if((v[i] == 0) && (same(ff,tt)))
                flag = true;
        }
        if(flag) puts("NO");
        else puts("YES");
    }
    return 0;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章