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;
}