给定一棵树,可以合并花瓣,求最后叶节点个数
我们很多时候不是去模拟那个过程,而是找到等价的东西去维护去处理
#include<bits/stdc++.h>
using namespace std;
string a,b;
int n;
const int N = 4e5+10;
int h[N],ne[N],e[N],idx;
int ans;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void init(){
memset(h, -1, sizeof h);
idx=0;
//memset(e,0,sizeof e);
//memset(ne,0,sizeof ne);
ans=1;
}
int dfs(int u,int fa){
int cnt=0;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa)continue;
cnt+=dfs(j,u);//cnt计算的是有多少个儿子
}
if(cnt>0){
ans+=cnt-1;
return 0;
//这个儿子可以拆出来不用统计到父节点,而是统计到答案里去
}
return 1;//叶子节点返回一
}
void solve(){
init();
cin>>n;
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1,-1);
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--)solve();
}
有一个n行m列的表格
有n*m个人 每个人都有一个等级ai 题目中给出
对于任意两个人 i j 若ai>aj 则si>sj
其中si=第i个人坐的位置
假设坐(x,y) si= x*m+j
从1-n*m开始选座位 一个人进入每行时 他的不舒服程度 = 该行前面的的人数
问你最小不舒服程度
其实就是双关键字排序,值val就是第一关键字,按照
val升序排列,越小的排在越前面,如果val相等就按照下标升序排列
然后遍历每一行,进行cmp2排序
val相等的要降序排列
然后计算升序对数量
ans+=cal(i)
这里给出非离散化版本和离散化版本
#include<bits/stdc++.h>
using namespace std;
const int N = 301;
struct node{
int val,index;
}a[N*N];
int n,m;
bool cmp1(node &x,node &y){
if(x.val==y.val)return x.index<y.index;
return x.val<y.val;
}
bool cmp2(node &x,node &y){
if(x.val==y.val)return x.index>y.index;
return x.val<y.val;
}
int cal(int i){
int cnt=0;//确定升序对数量
//确定每一行的左右端点
int l=(i-1)*m+1;//左端点确定
int r=i*m;//右端点确定
sort(a+l,a+r+1,cmp2);
// k j这样的排列是否升序
for(int j=r;j>l;j--){
for(int k=j-1;k>=l;k--){
if(a[k].index<a[j].index)cnt++;
}
}
return cnt;
}
void solve(){
int ans=0;
cin>>n>>m;
for(int i=1;i<=n*m;i++){
int x;
cin>>x;
a[i]={x,i};
}
sort(a+1,a+n*m+1,cmp1);
for(int i=1;i<=n;i++)ans+=cal(i);
cout<<ans;
cout<<'\n';
}
signed main(){
int T;
cin>>T;
while(T--)solve();
}
#include<bits/stdc++.h>
using namespace std;
const int N = 301;
struct node{
int val,index;
}a[N*N];
int n,m;
vector<int>b;
int find(int val){
int l=0,r=b.size()-1;
while(l<r){
int mid=l+r>>1;
if(b[mid]>=val)r=mid;
else l=mid+1;
}
return r+1;
}
bool cmp1(node &x,node &y){
if(x.val==y.val)return x.index<y.index;
return x.val<y.val;
}
bool cmp2(node &x,node &y){
if(x.val==y.val)return x.index>y.index;
return x.val<y.val;
}
int cal(int i){
int cnt=0;//确定升序对数量
//确定每一行的左右端点
int l=(i-1)*m+1;//左端点确定
int r=i*m;//右端点确定
sort(a+l,a+r+1,cmp2);
// k j这样的排列是否升序
for(int j=r;j>l;j--){
for(int k=j-1;k>=l;k--){
if(a[k].index<a[j].index)cnt++;
}
}
return cnt;
}
void solve(){
b.clear();
int ans=0;
cin>>n>>m;
for(int i=1;i<=n*m;i++){
int x;
cin>>x;
a[i]={x,i};
b.push_back(x);
}
sort(b.begin(),b.end());
b.erase(unique(b.begin(),b.end()),b.end());
for(int i=1;i<=n*m;i++)a[i].val=find(a[i].val);
sort(a+1,a+n*m+1,cmp1);
for(int i=1;i<=n;i++)ans+=cal(i);
cout<<ans;
cout<<'\n';
}
signed main(){
int T;
cin>>T;
while(T--)solve();
}
补了6道题收获还是蛮大的