NOIP2013火柴排队
Solution
恕我直言,这题是真的坑。
对于这道题,一个很显然的思路是对于A B两个序列,他们交换完后相对的两个数在原序列中的相对大小是相同的,于是我们就把序列按照A排序,在把B离散化,求逆序对,诶,这题真水。
期望得分100,实际得分10。
WTF???我写挂了??
正解,将A,B分别排序,c[a[i].pos]=b[i].pos,再将c求一波逆序对。
为什么这样可以,而上一种做法不行?
随便举个栗子
2 4 5 6 1 3
3 4 1 6 5 2
这是离散化后的序列,我们固定A序列,让B序列动,那么对于B序列来说,3应当在第六个,4应当在2个,1应当在第五个,6应当在第四个,5应当在第三个,2应当在第一个。于是B序列就变成了
6 2 5 4 3 1
这就是正解的合理性,而错误解法通过直接排序,将相邻元素的相对顺序打乱了,导致求出的解一定是错的(但是样例都能过【喷血】)。
Code
#include<iostream> #include<cstdio> #include<algorithm> #define mod 99999997 #define N 100009 using namespace std; long long n,tot,tr[N],c[N]; long long ans; struct de { long long a,b; }a[N],b[N]; void add(int u) { while(u<=n) { tr[u]++; tr[u]%=mod; u+=u&-u; } } long long q(int u) { long long an=0; while(u) { an+=tr[u]; u-=u&-u; } return an; } bool cmp(de a,de b) { return a.a<b.a; } int main() { scanf("%lld",&n); for(int i=1;i<=n;++i) scanf("%lld",&a[i].a),a[i].b=i; for(int i=1;i<=n;++i) scanf("%lld",&b[i].a),b[i].b=i; sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp); for(int i=1;i<=n;++i) c[a[i].b]=b[i].b; for(int i=1;i<=n;++i) { (ans+=i-q(c[i])-1)%=mod; add(c[i]); } // for(int i=1;i<=n;++i) // cout<<c[i]<<" "; cout<<ans; return 0; }
最后一句话
Think twice,code once