文章目录
A. Life of a Flower
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=110;
int w[N];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for( int i=1;i<=n;i++){
cin>>w[i];
}
int flag=1;
for( int i=2;i<=n;i++){
if(w[i]==0&&w[i-1]==0){
flag=0;
}
}
if(flag==0){
cout<<-1<<endl;
continue;
}
int ans=1;
for( int i=1;i<=n;i++){
if(w[i]==1&&w[i-1]==0) ans++;
if(w[i]==1&&w[i-1]==1) ans+=5;
}
cout<<ans<<endl;
}
return 0;
}
B. Array Eversion
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=200100;
int w[N];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int maxn=0;
for( int i=1;i<=n;i++){
cin>>w[i];
maxn=max(maxn,w[i]);
}
int ans=0;
int x=0;
for( int i=n;i>=1;i--){
if(maxn==w[i]) break;
if(w[i]>x) {
ans++;
x=w[i];
}
}
cout<<ans<<endl;
}
return 0;
}
C. Minimize Distance
贪心算法
将正数和负数分别存储,然后排序
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=200100;
vector<int>pos,neg;
int main(){
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
pos.clear();
neg.clear();
int maxn=0;
long long ans=0;
for( int i=1;i<=n;i++){
int x;
cin>>x;
if(x>=0) pos.push_back(x);
else neg.push_back(-x);
maxn=max(maxn,abs(x));
}
sort(pos.begin(),pos.end());
sort(neg.begin(),neg.end());
if(!pos.empty()){
for (int i=(pos.size())-1;i>=0;i-=k) {
ans+=2*pos[i];
}
}
if(!neg.empty()){
for( int i=(neg.size())-1;i>=0;i-=k){
ans+=2*neg[i];
}
}
cout<<ans-(long long)maxn<<endl;
}
return 0;
}
D. Yet Another Sorting Problem
考察的是排列的奇偶性。
对于某个排列,某个元素的值为i,将i和第i个位置的数连上一条边。
那么排列的奇偶性就是n-环数
排列的奇偶性也可以通过求解逆序对的对数来求解。
对于某个排列,如果交换两个元素,会改变排列的奇偶性。
本题中,交换三个元素,排列的奇偶性不变,由于最后的奇偶性是偶数,所以如果最后的奇偶性是偶数,那么就可以排序,反之不能排序。
如果有多个相同元素,那么交换后奇偶性改变,但是数组不变,因此一定有解。
判断图中有几个环,用并查集即可,因为环是强连通的,
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=500100;
int w[N];
int fa[N];
int find(int x){
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
set<int>se;
for( int i=1;i<=n;i++){
cin>>w[i];
se.insert(w[i]);
fa[i]=i;
}
if(n==1||se.size()<n){
cout<<"YES"<<endl;
continue;
}
if(n==2){
if(w[1]<=w[2]) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
continue;
}
int cyc=n;
for( int i=1;i<=n;i++){
if(find(i)==find(w[i])) cyc--;//有环
else {
fa[find(i)]=find(w[i]);
}
}
if(cyc%2==0){
cout<<"YES"<<endl;
}
else {
cout<<"NO"<<endl;
}
}
return 0;
}
E. Frequency Queries
cf的数据结构太肝了。。。。。
首先dfs求出每个结点的时间戳,然后把询问按时间戳排序,然后按时间戳的顺序求解答案。
对于每次寻问,我们需要维护一平衡树,平衡树按照每个数值出现的次数排序,
需要一个数组维护每个数值出现的次数,这样才能实现在树中查找pair的数据类型。
对于每次查找,首先找到小于x的数的个数,然后再找到答案的值。
最后将答案统一输出。
这里有几个技巧,再pbds平衡树中用pair当作元素需要修改比较函数,在比较时先比较第一个元素,在比较第二个元素
#include<bits/stdc++.h>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
const int N=1000100;
const int inf=0x3f3f3f3f;
tree<pair<int,int> , null_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update>tr;
//平衡树,按照每个数的出现次数排序,第二关键字是a
int p[N],a[N];
//首先求解dfs序和时间戳
int cnt[N],step[N];//每个数的个数,时间戳
int cc,point;
int h[N],ne[N*2],to[N*2],idx;
int ans[N];
int n,q;
struct query{
int v,l,k,id;
}qq[N];
void add( int a,int b){
to[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void get_step(int rt,int fa){
step[rt]=cc++;
for( int i=h[rt];i!=-1;i=ne[i]){
int j=to[i];
if(j==fa) continue;
get_step(j,rt);
}
}
int cmp( query a,query b){
return step[a.v]<step[b.v];
}
#define debug cout<<"debug::"<<rt<<step[qq[point].v]<<step[rt]<<endl;
void solve(int rt,int fa){
int x=a[rt];
if(cnt[x])
tr.erase(make_pair(cnt[x],x));
cnt[x]++;
tr.insert(make_pair(cnt[x],x));
while(step[qq[point].v]<step[rt]&&point<=q) point++;
while(qq[point].v==rt&&point<=q){
int cnt_pre=tr.order_of_key(make_pair(qq[point].l,-1));
tree<pair<int,int> , null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>::iterator it;
it=tr.find_by_order(cnt_pre+qq[point].k-1);
if(it==tr.end()) ans[qq[point].id]=-1;
else ans[qq[point].id]=it->second;
point++;
}
for( int i=h[rt];i!=-1;i=ne[i]){
int j=to[i];
if(j==fa) continue;
solve(j,rt);
}
tr.erase(make_pair(cnt[x],x));
cnt[x]--;
if(cnt[x])
tr.insert(make_pair(cnt[x],x));
}
int main(){
int t;
cin>>t;
while(t--){
scanf("%d%d",&n,&q);
cc=0,idx=0,point=1;
for( int i=1;i<=n;i++){
h[i]=-1;
scanf("%d",&a[i]);
}
for( int i=2;i<=n;i++){
int x;
scanf("%d",&x);
add(x,i);
add(i,x);
}
get_step(1,0);
step[n+1]=inf;
for( int i=1;i<=q;i++){
scanf("%d%d%d",&qq[i].v,&qq[i].l,&qq[i].k);
qq[i].id=i;
}
sort(qq+1,qq+1+q,cmp);
solve(1,0);
for( int i=1;i<=q;i++){
printf("%d ",ans[i] );
}
printf("\n");
}
return 0;
}