int main(){
while(模拟赛) 降智++;
return inf;
}
T1
刚看到题时还以为不可做,重新看了几遍之后才发现以前好像做过……
做法很显然吧……
由于第一行存在 $1-n$ 的数各一个,我们可以先把列 按照第一行的数从大到小排序,这样第 $i$ 列第 $1$ 行的数就是 $i$ 了,方便后续操作。
容易发现,如果第 $2$ 或 第 $3$ 行不存在某个数,那第一行的这个数肯定匹配不上 $2$、$3$ 行相同的数,把这个数在第一行所在的那一列删掉。
然后删掉一列之后,第 $2$、$3$ 行就各少了一个数,那第 $2$ 或 第 $3$ 行就有可能又出现一个不存在的数。重复上述删除过程即可。
可以把要删除的列的编号扔进一个队列,挨个取出后操作。时间复杂度是列数级别,即 $O(n)$。
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read(){ 4 int x=0; bool f=1; char c=getchar(); 5 for(;!isdigit(c);c=getchar()) if(c=='-') f=0; 6 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0'); 7 if(f) return x; 8 return 0-x; 9 } 10 int n; 11 struct num{ 12 int v[4]; 13 bool operator <(const num &x)const{ 14 return v[0]<x.v[0]; 15 } 16 }a[100002]; 17 int cnt[100002],_cnt[100002],ans; 18 bool del[100002]; 19 int main(){ 20 freopen("avogadro.in","r",stdin); 21 freopen("avogadro.out","w",stdout); 22 n=read(); 23 int i,j; 24 for(i=0;i^3;++i) 25 for(j=1;j<=n;++j) 26 a[j].v[i]=read(); 27 sort(a+1,a+n+1); 28 for(i=1;i<=n;++i) ++cnt[a[i].v[1]], ++_cnt[a[i].v[2]]; 29 queue<int>Q; 30 for(i=1;i<=n;++i) if(!cnt[i] || !_cnt[i]) Q.push(i), del[i]=1; 31 int u; 32 while(!Q.empty()){ 33 u=Q.front(), Q.pop(); 34 ++ans; 35 //printf("%d %d %d %d\n",u,a[u].v[1],a[u].v[2],ans); 36 if(--cnt[a[u].v[1]]==0 && !del[a[u].v[1]]) del[a[u].v[1]]=1, Q.push(a[u].v[1]); 37 if(--_cnt[a[u].v[2]]==0 && !del[a[u].v[2]]) del[a[u].v[2]]=1, Q.push(a[u].v[2]); 38 } 39 printf("%d\n",ans); 40 return 0; 41 }