原题链接
思路:
首先将原序列分为两类:有正序对的和没有正序对的.
对于有正序对的序列,统计其个数.
对于没有正序对的序列,记录其最大值和最小值。用数组 Amax 与 Amin 存储.
假设合成的序列为 A+B, 则 A+B 有正序对有正序对的条件为:
- A 或 B 有正序对
或
- A,B 均无正序对且 A 的最小值小于 B 的最大值
对于条件 (2),
将数组 Amin 与 Amax 排序后可用尺取法计数.
对于条件 (1), 假设有 c 个有正序对的序列,
使用容斥原理可得其数量为 2*c*n-n*n
需要注意的是答案有可能超出 int 范围,所以要用 long long 类型
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <cstdio> #include <algorithm> using namespace std; const int Mn(100500); int amin[Mn],amax[Mn]; int main() { int n; scanf("%d",&n); int cac(0),cdc(0); for(int i(1);i<=n;++i) { int l; scanf("%d",&l); int la(0x7fffffff),amn(0x7fffffff),amx(0); bool isac(false); for(int i(1);i<=l;++i) { int a; scanf("%d",&a); amn = a<amn ? a : amn; amx = a>amx ? a : amx; if(a>la) isac = true; la = a; } if(isac) ++cac; else { amax[++cdc]=amx; amin[cdc]=amn; } } sort(amax+1,amax+cdc+1); sort(amin+1,amin+cdc+1); amax[0] = -1; long long ans(0); int pmn(1),pmx(0); for(;pmn<=cdc;++pmn) { for(;pmx<=cdc;++pmx) if(amax[pmx]>amin[pmn]) break; ans += cdc-pmx+1; } ans += 2ll*cac*n-1ll*cac*cac; printf("%lld",ans); return 0; }
|