4.2
https://vjudge.net/contest/156696
这是2014年多校5的比赛重新开了一遍
A题
题意:给你长度为n的序列,问让你进行最多k次相邻的数之间交换之后序列的最小逆序数是多少
思路:先求当前数的最小逆序数num,然后num-k即为最后的结果。由于n挺大的直接进行计算的话时间复杂度是O(n^2)所以使用线段树缩小时间复杂度到(log(n))。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=100005; 7 struct node 8 { 9 long long id,num; 10 } a[maxn]; 11 long long cmp(const node &x,const node &y) 12 { 13 if(x.num!=y.num) 14 return x.num>y.num; 15 else 16 return x.id>y.id; 17 } 18 struct Node 19 { 20 int l,r,m; 21 }b[maxn<<2]; 22 void build(int l,int r,int k) 23 { 24 b[k].l=l,b[k].r=r,b[k].m=0; 25 if(l==r) 26 { 27 return ; 28 } 29 int mid=(l+r)/2; 30 build(l,mid,k*2); 31 build(mid+1,r,k*2+1); 32 return ; 33 } 34 void init(int d,int k) 35 { 36 if(b[k].l==b[k].r&&b[k].r==d) 37 { 38 b[k].m=1; 39 return ; 40 } 41 if(d>b[k*2].r) init(d,k*2+1); 42 else init(d,k*2); 43 b[k].m=b[k*2].m+b[k*2+1].m; 44 return ; 45 } 46 int query(int l,int r,int k) 47 { 48 if(b[k].l==l&&b[k].r==r) 49 { 50 return b[k].m; 51 } 52 int ans=0; 53 if(l>b[k*2].r) ans+=query(l,r,k*2+1); 54 else if(r<=b[k*2].r) ans+=query(l,r,k*2); 55 else 56 { 57 ans+=query(l,b[k*2].r,k*2); 58 ans+=query(b[k*2].r+1,r,k*2+1); 59 } 60 return ans; 61 } 62 int main() 63 { 64 long long n,k; 65 while(~scanf("%lld%lld",&n,&k)) 66 { 67 for(long long i=0; i<n; i++) 68 { 69 scanf("%lld",&a[i].num); 70 a[i].id=i; 71 } 72 sort(a,a+n,cmp); 73 long long ans=0; 74 int tmp=0; 75 build(0,n-1,1); 76 for(long long i=0; i<n; i++) 77 { 78 long long p=a[i].id; 79 init(p,1); 80 tmp=0; 81 if(p!=0) 82 tmp=query(0,p-1,1); 83 ans+=tmp; 84 } 85 if(ans>k) 86 printf("%lld\n",ans-k); 87 else 88 printf("0\n"); 89 } 90 return 0; 91 }
B题
C题
D题
E题
题意:给你由‘(’、‘)’、和‘?’三种字符组成的字符串,问是否能够进行括号匹配,如果能是仅有一种匹配还是有多种?
F题
G题
H题
I题
J题