PTA团体程序设计天梯赛
数据结构类型
L3-002 特殊堆栈(树状数组)
题目大意
本题的难点是维护一个动态的中值。
解题思路
因为值可能是不按大小顺序给出的,因此我们无法利用优先队列来维护,原因是在进行pop的时候可能弹出的是下边或者中间的值,而不是优先队列顶部的值。对于中值,我们对于每一个值如果出现一次,那么其次数加1,那么中值就转变为了这个次数序列中出现次数的中值(因为这个序列是单调的),那么可以单点修改与单点查询的数据结构,就是树状数组了。
- 对于求中值,我们可以在0 ~ N 中进行二分。
代码:
#include<iostream>
#include<string>
#include<stack>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int t[N];
stack<int>st;
int n ,x;
int lowbit(int x){
return x & -x; }
void add(int k , int v){
for( ; k < N ; k += lowbit(k)) t[k] += v;
}
int get(int n){
int ans = 0;
for( ; n ; n -= lowbit(n))ans += t[n];
return ans;
}
int PeekMedian(){
int l = 1 , k = (st.size() + 1)/2 , r = N - 1;
while(l < r){
int mid = (l + r)>>1;
if(get(mid) >= k) r = mid;
else l = mid + 1;
}
return l;
}
int main(){
cin>>n;
while(n--){
string s;
cin>>s;
if(s == "Pop"){
if(st.size() == 0)cout<<"Invalid\n";
else{
x = st.top();
cout<<st.top()<<endl;
st.pop() , add(x , -1);
}
}else if(s == "Push"){
cin>>x;
st.push(x) ,add(x,1);
}else{
if(st.size() == 0)cout<<"Invalid\n";
else cout<<PeekMedian()<<endl;
}
}
return 0;
}
L3-003 社交集群(并查集)
题目大意
题目是给出了每一个人的兴趣的编号的集合,对于存在一个兴趣相同的人我们认为其在一个圈子中。然后问你有多少兴趣圈,与每一个圈子有多少人。
解题思路
对于每一个人我们存下,其兴趣圈中的一个代表元素(不妨是第一个元素),之后将其兴趣圈中的所有值进行合并。对于没一个人都这样操作以后。我们枚举这n个人,我们
代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1100;
int p[N];
char ch;
int n , f[N];
int pos[N] ,cnt , p[N];
bool cmp(int a, int b){
return a > b;}
void init(){
for(int i = 1 ;i < N ; ++i) f[i] = i;
}
int find(int x){
if(x == f[x])return x;
else return f[x] = find(f[x]);
}
void join(int x,int y){
x = find(x) , y = find(y);
if(x != y)f[x] = y;
}
int main(){
cin>>n;
init();
for(int i = 1 ; i <= n ; ++i){
int k , y ;
cin>>k>>ch;
for(int j = 1 ;j <= k ; ++j){
int x;
cin>>x;
if(j == 1)y = x , p[i] = y;
else join(x ,y);
}
}
for(int i = 1; i <= n ; ++i)
{
int x = find(p[i]);
pos[x] ++;
}
sort(pos ,pos + N , cmp);
for(int i =

最低0.47元/天 解锁文章
229

被折叠的 条评论
为什么被折叠?



