#include<iostream> #include<stdio.h> #include<vector> #include<queue> #include<algorithm> #include<memory.h> #include<string.h> #include<cmath> #include<map> #include<set> #define INF 0x3f3f3f3f #define PII pair<int,int> #define MOD 1000000000 #define MAX_N 1000 using namespace std; int n,m,w,x,y,tmp; int xx[100005]; int a[100005]; int ans[100005]; int max_n=0; int lowbit(int x) { return x&(-x); } int sum(int x) { int res=0; while(x) { res+=a[x]; x-=lowbit(x); } return res; } void add(int x) { while(x<=max_n) { a[x]++; x+=lowbit(x); } } int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>x>>y; xx[i]=x+1; max_n=max(x+1,max_n); } for(int i=1;i<=n;i++) { int t=sum(xx[i]); add(xx[i]); ans[t]++; } for(int i=0;i<=n-1;i++) cout<<ans[i]<<endl; return 0; }
#include<iostream> #include<stdio.h> #include<vector> #include<queue> #include<algorithm> #include<memory.h> #include<string.h> #include<cmath> #include<map> #include<set> #define INF 0x3f3f3f3f #define PII pair<int,int> #define MOD 1000000000 #define MAX_N 1000 using namespace std; int n,m,w,x,y,tmp; int xx[100005]; int a[100005]; int ans[100005]; int max_n=0; int lowbit(int x) { return x&(-x); } int sum(int x) { int res=0; while(x) { res+=a[x]; x-=lowbit(x); } return res; } void add(int x,int num) { while(x<=n) { a[x]+=num; x+=lowbit(x); } } int main() { //cout<<6+lowbit(6)<<endl; memset(a,0,sizeof(a)); cin>>n; for(int i=1;i<=n;i++) { cin>>x>>y; //xx[i]=x; add(x,1); add(y+1,-1); //max_n=max(x,max_n); } for(int i=1;i<=n;i++) if(i!=n) cout<<sum(i)<<" "; else cout<<sum(i)<<endl; //cout<<res<<endl; return 0; }
一次有效的交换意味着什么呢?
为了使序列有序,一次有效的交换应该是后一个较小的数与他前一个较大的数交换,那么单独一个数字的交换次数,应该是这个数字前面比它大的数字的个数。
#include<iostream> #include<algorithm> #include<memory.h> using namespace std; long long a[500005]; long long b[500005]; long long c[500005]; long long n,t; long long lowbit(long long x) { return x&(-x); } long long sum(long long x) { long long res=0; while(x) { res+=c[x]; x-=lowbit(x); } return res; } void add(long long x) { while(x<=n) { c[x]++; x+=lowbit(x); } } int main() { memset(c,0,sizeof(c)); cin>>n; for(long long i=1;i<=n;i++) { cin>>a[i]; b[i]=a[i]; } sort(a+1,a+1+n); long long res=0; for(long long i=1;i<=n;i++) { //index = 小于b[i]的元素个数+1 //即b[i] 被映射成了 index long long index=lower_bound(a+1,a+1+n,b[i])-a; long long upper_num=i-1-sum(index-1); add(index); res+=upper_num; } cout<<res<<endl; return 0; }
如果我们知道最后一个人,他前面有 i 个比他小的编号,那么他的编号一定是 i+1。那么我们是不是可以从后往前来确定每个人的编号呢。
#include<iostream> #include<stdio.h> #include<memory.h> using namespace std; int a[500005]; int c[500005]; int flag[500005]; int res[500005]; int n,t; int lowbit(int x) { return x&(-x); } int sum(int x) { int res=0; while(x) { res+=c[x]; x-=lowbit(x); } return res; } void add(int x,int num) { while(x<=n) { c[x]+=num; x+=lowbit(x); } } int main() { memset(c,0,sizeof(c)); memset(flag,0,sizeof(flag)); scanf("%d",&n); for(int i=2;i<=n;i++) scanf("%d",&a[i]); //最后一个点的编号 res[n]=a[n]+1; add(res[n],1); flag[res[n]]=1; for(int i=n-1;i>1;i--) { //初始位置 int t=a[i]+1; int l=0,r=n,pianyi; //二分枚举偏移量 while(l<=r) { int mid=(l+r)>>1; if(mid+t>n) { mid=n-t; r=2*(n-t)-l; } int k=sum(mid+t); if(mid>k) { r=mid-1; } if(mid<k) { l=mid+1; } if(mid==k) { pianyi=mid; r=mid-1; } } res[i]=t+pianyi; flag[res[i]]=1; add(res[i],1); } for(int i=1;i<=n;i++) { if(!flag[i]) { res[1]=i; break; } } for(int i=1;i<=n;i++) printf("%d\n",res[i]); return 0; }
时间: 2024-10-22 10:02:08