洛谷——《集合》

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<set>
#include<map>
#include<algorithm>
#include<cmath>
using namespace std;


//p1551
// int n,m,p;
// int a,b;
// int arr[5100];

// int find(int x)
// {
//     while(arr[x]!=x)x = arr[x];
//     return x;
// }
// int main()
// {
//     cin>>n>>m>>p;
//     for(int i =1;i<=n;i++)arr[i] = i;
//     for(int i =0;i<m;i++)
//     {
//         cin>>a>>b;
//         arr[find(a)] = arr[find(b)];//统一将左边的根父节点设置为右边的根节点
//     }
//     for(int i =0;i<p;i++)
//     {
//         cin>>a>>b;
//         if(find(a)==find(b))cout<<"Yes"<<endl;
//         else cout<<"No"<<endl;
//     }
// }


//p1536
// 1.建立完集合后重新遍历找有多少是根节点

// int n,m;
// int a,b;
// int arr[1100];

// int find(int x)
// {
//     if(arr[x]<=0)return x;
//     return find(arr[x]);
// }

// void Union(int x,int y)
// {
//     if(find(x)==find(y)&&find(x)!=-1)return;
//     if(arr[find(x)]<arr[find(y)])
//     {
//         arr[find(x)] +=arr[find(y)];
//         arr[find(y)] = find(x);
//     }
//     else 
//     {
//         arr[find(y)] +=arr[find(x)];
//         arr[find(x)] = find(y);
//     }
// }
// int main()
// {
//     cin>>n;
//     while(n!=0)
//     {
//         cin>>m;
//         memset(arr,-1,sizeof(int)*(n+1));//初始化
//         for(int i =0;i<m;i++)
//         {
//             cin>>a>>b;
//             Union(a,b);//合并集合
//         }
//         int ans = 0;
//         for(int i =1;i<=n;i++)
//         {
//             if(arr[i]<0)ans++;
//         }
//         cout<<ans-1<<endl;
//         cin>>n;
//     }
// }


//p3370
// int n,ans;
// string s;
// vector<string>arr[23335];
// void insert(string t)
// {
//     int hash = 1;
//     for(int i =0;i<t.length();i++)
//         hash = (hash*111*261+s[i])%23333;
//     for(int i =0;i<arr[hash].size();i++)
//     {
//         if(arr[hash][i]==t)return;
//     }
//     arr[hash].push_back(t);
//     ans++;
// }
// int main()
// {
//     cin>>n;
//     for(int i =0;i<n;i++)
//     {
//         cin>>s;
//         insert(s);
//     }
//     cout<<ans;
// }



// p3405
// #define mod 233333
// string s1,s2;
// long long n,ans;
// vector<string>arr[mod+2];
// int gethash(string s)
// {
//     return ((s[0]-'A')+(s[1]-'A')*26+(s[2]-'A')*26*26+(s[3]-'A')*26*26*26)%mod;
// }
// void insert(string s)
// {
//     string t = s;
//     int hash = 1;
//     hash = gethash(s);
//     //存放位置
//     arr[hash].push_back(s);
//     t = s.substr(2)+s.substr(0,2);//逆转
//     //查找匹配
//     hash = gethash(t);//清理
//     for(int i=0;i<arr[hash].size();i++)
//     {
//         if(arr[hash][i]==t)ans++;
//     }   
// }
// int main()
// {
//     cin>>n;
//     for(int i =0;i<n;i++)
//     {
//         cin>>s1>>s2;
//         s1 = s1.substr(0,2)+s2;
//         if(s1.substr(0,2)!=s2)insert(s1);//真受不了,就是因为这个地方搞了好久,没有的话才10分
//     }
//     cout<<ans;
// }


//p5250

//set<int>ds 建立集合
//ds.insert(x)
//ds.erase(x)
//ds.erase(it)
//ds.end()
//ds.find()
//ds.lower_bound(x)
//ds.upper_bound(x)
//ds.empty()
//ds.size()

// int n;
// int op,len;
// set<int> ds;
// int main()
// {
//     cin>>n;
//     for(int i =0;i<n;i++)
//     {
//         cin>>op>>len;
//         if(op==1)
//         {
//             if(ds.find(len)!=ds.end())cout<<"Already Exist"<<endl;//有库存
//             else ds.insert(len);//放入集合中
//         }
//         else if(ds.empty())cout<<"Empty"<<endl;
//         else
//         {
//             set<int>::iterator i = ds.lower_bound(len),j = i;
//             if(j!=ds.begin())--j;//获得不小于i第一个的位置
//             if(i!=ds.end()&&len-(*j)>(*i)-len)j = i;
//             cout<<(*j)<<endl,ds.erase(j);
//         }
//     }
// }


//p5266
// map<A,B>_ds 建立下标类型为A,元素类型为B的映射表
// ds[A] = B 将下标为A的值变成B
// ds[A] 访问下标为A的元素
// ds.end()
// ds.find(x)
// ds.empty()
// ds.size()
// ds.erase(A)删除下标为A的元素


// int op,score;
// string name;
// int main()
// {
//     int n;
//     cin>>n;
//     map<string,int>ds;
//     for(int i=0;i<n;i++)
//     {
//         cin>>op;
//         if(op==1)
//         {
//             cin>>name>>score;
//             ds[name] = score;//建立或修改
//             cout<<"OK"<<endl;
//         }
//         else if(op==2)
//         {
//             cin>>name;
//             if(ds.find(name)!=ds.end()) cout<<ds[name]<<endl;//返回分数
//             else cout<<"Not found"<<endl;
//         }
//         else if(op==3)
//         {
//             cin>>name;
//             if(ds.find(name)!=ds.end()) 
//             {
//                 ds.erase(name);//返回分数
//                 cout<<"Deleted successfully"<<endl;
//             }
//             else cout<<"Not found"<<endl;
//         }
//         else
//         {
//             cout<<ds.size()<<endl;
//         }
//     }
// }

//p1918
//通过值访问下标,不能用set
// long long n,a,q,val;
// main()
// {
//     cin>>n;
//     map<long long,long long> ds;//一个存下标一个存值
//     for(long long i =1;i<=n;i++)
//     {
//         cin>>a;
//         ds[a] = i;//位置瓶子数目
//     }
//     cin>>q;
//     for(long long i =1;i<=q;i++)
//     {
//         cin>>val;
//         if(ds.find(val)!=ds.end())
//         {
//             cout<<ds[val]<<endl;
//         }
//         else cout<<0<<endl;
//     }
// }


//p1525
//感觉自己目前这个水平做蓝题还是不行啊
// 1.存数据:两个囚犯,仇恨值
// 2.将该结构体按照仇恨值排序(仇恨值越大的两个囚犯要优先分开,直到两个囚犯不得不在一块的时候,此时的仇恨值是最小)
// 3.分开操作:用并查序代表不同的集合(至少会有两个集合),将自己的目前敌人放在先前敌人的集合中,敌人也要这么做

// struct Node
// {
//     int from,to,e;
// }arr[110000];

// int n,m,a,b,c;
// int f[21000],enemy[21000];//并查序
// bool cmp(Node a,Node b)
// {
//     return a.e>b.e;//大的仇恨值排在前面
// }
// int find(int x)
// {
//     if(f[x]==x)return x;//本身就是根
//     return find(f[x]);//继续找父节点
// }
// int main()
// {
//     cin>>n>>m;
//     //初始化
//     for(int i = 1;i<=n;i++)
//     {
//         f[i] = i;
//     }
//     for(int i =1;i<=m;i++)
//     {
//         cin>>arr[i].from>>arr[i].to>>arr[i].e;
//     }
//     sort(arr+1,arr+m+1,cmp);//排序
//     for(int i =1;i<=m;i++)//遍历仇恨值
//     {
//         a = find(arr[i].from),b = find(arr[i].to);//获得两个集合的根
//         if(a==b)
//         {
//             cout<<arr[i].e;
//             return 0;//不可避免的在一个监狱了
//         }
//         //放入之前仇恨对象的集合中(需要记录之前的仇恨对象,一个就可以了)
//         if(!enemy[arr[i].from])enemy[arr[i].from] = arr[i].to;//没有先前仇恨对象时
//         else
//         {
//             f[find(arr[i].to)] = find(enemy[arr[i].from]);//敌人的父节点是先前敌人的根
//         } 
//         if(!enemy[arr[i].to])enemy[arr[i].to] = arr[i].from;//没有先前仇恨对象时
//         else
//         {
//             f[find(arr[i].from)] = find(enemy[arr[i].to]);//敌人的父节点是先前敌人的根
//         } 
//     }
//     cout<<0;//没有矛盾
// }


// p1621
// 1.用并查集
// 2.搞定一次的合并,递归直到不存在合并
// 3.合并条件:有公共质约数(80分)
// int a,b,p,ans;
// int f[100000];//父节点
// map<int,int>ds;//对应根的总值

// int find(int x)
// {
//     if(f[x]==x)return x;
//     return find(f[x]);
// }
// bool zhishu(int x)
// {
//     if(x<=1)return 0;
//     for(int i =2;i<=sqrt(x);i++)
//     {
//         if(x%i==0)return 0;
//     }
//     return 1;
// }
// bool yueshu(int a,int b)
// {
//     int i =min(a,b);
//     for(int j =p;j<=i;j++)
//     {
//         if(a%j==0&&b%j==0&&zhishu(j))return 1;
//     }
//     return 0;
// }

// void Union()
// {
//     int flag = 0;
//     for(int i = a;i<b;i++)//遍历一遍
//     {
//         for(int j = i+1;j<=b;j++)
//         {
//             if(find(f[i])==find(f[j]))continue;
//             if(yueshu(ds[i],ds[j]))
//             {
//                 f[find(j)] = find(i);
//                 ds[find(i)] +=ds[find(j)];
//                 flag = 1;
//             }
//         }
//     }
//     if(flag==0)return;
//     Union();
// }
// int main()
// {
//     cin>>a>>b>>p;
//     for(int i =a;i<=b;i++)
//     {
//         f[i] = i;//初始化
//         ds[i] = i;
//     }
//     Union();
//     for(int i =a;i<=b;i++)
//     {
//         if(f[i]==i)ans++;
//     }
//     cout<<ans;
// }


//p1892
// 1.并查集统计集合数目为团体数目
// 2.朋友的朋友是朋友很好理解,直接将两个朋友集合合并就可以
// 3.敌人的敌人是朋友,那就要记录敌人的敌人这个集合,再将两者合并

// int f[1100];
// int enemy[1100];//记录敌人
// int n,m,p,q,ans;
// char opt;
// int find(int x)
// {
//     if(f[x]==x)return x;
//     return find(f[x]);
// }
// void Union(int a,int b)
// {
//     if(find(a)==find(b))return;
//     f[find(b)] = find(a);
// }
// int main()
// {
//     cin>>n>>m;
//     for(int i =1;i<=n;i++)f[i] = i;
//     for(int i =0;i<m;i++)
//     {
//         cin>>opt>>p>>q;
//         if(opt =='F')
//         {
//             Union(p,q);//直接合并
//         }
//         else
//         {
//             if(!enemy[p])enemy[p] = find(q);
//             else Union(enemy[p],q);
//             if(!enemy[q])enemy[q] = find(p);
//             else Union(enemy[q],p);
//         }
//     }
//     for(int i =1;i<=n;i++)
//     {
//         if(f[i]==i)ans++;
//     }
//     cout<<ans;
// }



//p1955
// 1.相等的数放入同一个集合
// 2.如果不相等,判断是不是在这个集合中,如果在,则矛盾
// 空间太大,考虑改用
// int t,n,e,cnt,Max;
// long long i,j;
// int reu;
// int book[1100000*3];//记录内容的位置

// int f[1100000];//一个存内容一个存父节点(查找方式用二分查找,需要排序)
// struct Node
// {
//     int a,b;
//     bool w;
// }arr[1100000];//记录数据

// int find(int x)//获得根节点
// {
//     while(f[x]!=x)x = f[x];
//     return x;
// }
// void Union(int a,int b)
// {
//     f[find(b)] = find(a);
// }
// bool cmp(Node a,Node b){
//     return a.w>b.w;
// }//排 序将e==1的放在前面 
// int main()
// {
//     cin>>t;
//     while(t--)
//     {
//         cin>>n;        
//         cnt = 0;
//         int flag = 0;//标记
//         memset(book,0,sizeof(book));
//         memset(f,0,sizeof(f));
//         memset(arr,0,sizeof(arr));
//         for(int k =1;k<=n;k++)
//         {
            
//             cin>>arr[k].a>>arr[k].b>>arr[k].w;//初始化
//             book[++cnt] = arr[k].a,book[++cnt] = arr[k].b;//放入元素
//         }
//         sort(book,book+cnt);//从小到大排序
//         reu = unique(book,book+cnt)-book;//去重并得到当前数组长度
//         for(int k=1;k<=n;k++)
//         {
//            arr[k].a=lower_bound(book,book+reu,arr[k].a)-book;
//            arr[k].b=lower_bound(book,book+reu,arr[k].b)-book;   
//         } //将arr中的值改写
//         for(int k =1;k<=reu;k++)f[k] = k;//初始化
//         sort(arr+1,arr+n+1,cmp);
//         for(int k =1;k<=n;k++)
//         {    

//             if(arr[k].w==1)
//             {
//                 Union(arr[k].a,arr[k].b);
//             }
//             else
//             {
//                 if(find(arr[k].a)==find(arr[k].b))
//                 {
//                     cout<<"NO"<<endl;
//                     flag = 1;
//                     break;
//                 }
//             }
//         }
//         if(flag==0)cout<<"YES"<<endl;
//     }
// }


// const int MAXN = 1100000;
// int t, n, cnt;
// int f[MAXN], Rank[MAXN], book[MAXN * 3];

// struct Node {
//     int a, b;
//     bool w;
// } arr[MAXN];

// int find(int x) {
//     if (f[x] == x) return x;
//     return f[x] = find(f[x]); // 路径压缩
// }

// void Union(int a, int b) {
//     int rootA = find(a);
//     int rootB = find(b);
//     if (rootA == rootB) return;
    
//     // 按秩合并
//     if (Rank[rootA] < Rank[rootB]) {
//         f[rootA] = rootB;
//     } else {
//         f[rootB] = rootA;
//         if (Rank[rootA] == Rank[rootB]) {
//             Rank[rootA]++;
//         }
//     }
// }

// bool cmp(Node a, Node b) {
//     return a.w > b.w;
// }

// int main() {
//     cin >> t;
//     while (t--) {
//         cin >> n;
        
//         cnt = 0;
//         int flag = 0;
//         memset(book, 0, sizeof(book));
//         for (int k = 1; k <= n; k++) {
//             cin >> arr[k].a >> arr[k].b >> arr[k].w;
//             book[++cnt] = arr[k].a;
//             book[++cnt] = arr[k].b;
//         }
        
//         sort(book + 1, book + cnt + 1);
//         int uniqueLen = unique(book + 1, book + 1 + cnt) - book;
        
//         for (int k = 1; k <= n; k++) {
//             arr[k].a = lower_bound(book + 1, book + uniqueLen, arr[k].a) - book;
//             arr[k].b = lower_bound(book + 1, book + uniqueLen, arr[k].b) - book;
//         }
        
//         for (int k = 1; k <= uniqueLen; k++) {
//             f[k] = k;
//             Rank[k] = 0;
//         }
        
//         sort(arr + 1, arr + n + 1, cmp);
        
//         for (int k = 1; k <= n; k++) {
//             if (arr[k].w) {
//                 Union(arr[k].a, arr[k].b);
//             } else {
//                 if (find(arr[k].a) == find(arr[k].b)) {
//                     cout << "NO" << endl;
//                     flag = 1;
//                     break;
//                 }
//             }
//         }
        
//         if (flag == 0) {
//             cout << "YES" << endl;
//         }
//     }
    
//     return 0;
// }

//p4305
//计数数组(60分)

// long long s = 1<<10;
// vector<int>arr[500000];
// int B[500000];
// int t,n,cnt;
// int main()
// {
//     ios_base::sync_with_stdio(false);
//     cin.tie(nullptr);
//     cin>>t;
//     while(t--)
//     {
//         cin>>n;
//         cnt =0;//清理
//         // for (int i = 0; i < 100000; ++i) {
//         //     arr[i].clear();
//         // }//这个太浪费时间了
//         for(int i =1;i<=n;i++)
//         {
//             long long item;
//             cin>>item;
//             long long a = (abs(item)/s)%500000;
//             long long b = abs(item)%s;
//             if(item<0)b = -b;
//             int flag = 0;
//             for(int j = 0;j<arr[a].size();j++)
//             {
//                 if(arr[a][j] == b)
//                 {
//                     flag = 1;
//                     break;
//                 }
//             }
//             if(!flag)
//             {
//                 cout<<item<<' ';
//                 arr[a].push_back(b);
//                 B[cnt++]= a;
//             }
//         }
//         for(int i =0;i<cnt;i++)
//         {
//             arr[B[i]].clear();//专门清理
//         }
//         cout<<endl;
//     }
// }

// 改用set(孩子要奔溃了,用了哈希,计数,map,set都不行,最后查答案试着找到关键问题,真的是意想不到)
// set<long long> ds;//一个是数字,一个是有没有存入
// int t,n;
// int main()
// {
//     //就是这两玩意,太nb了
//     ios_base::sync_with_stdio(false);//这个函数调用会解绑 C 和 C++ 的标准输入输出流,让它们各自独立缓冲区,提高 I/O 性能。在大多数情况下,C++ 的 iostream 库会与 C 的 stdio 库同步,这可能会带来一些性能开销。所以,如果不需要 C 和 C++ 标准 I/O 同步,可以把同步关掉,从而提升性能。
//     cin.tie(nullptr);//通过这行代码,取消了 cin 对 cout 的绑定。在C++中,默认情况下,cin 和 cout 是绑定在一起的,这意味着在每次读取输入时,输出缓冲区会被刷新。如果取消绑定,可以避免这种情况,提高 I/O 性能。
//     cin>>t;
//     while(t--)
//     {
//         cin>>n;
//         ds.clear();
//         for(int i =1;i<=n;i++)
//         {
//             long long item;
//             cin>>item;
//             if(ds.find(item)==ds.end())
//             {
//                 cout<<item<<' ';
//                 ds.insert(item);
//             }
//         }
//         cout<<endl;
//     }
// }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值