Description
https://www.luogu.com.cn/problem/CF725F
Solution
第一步都想错了,警戒!
考虑一个严格弱的问题:一堆照片只有一张的情况,有贪心策略两个人按 $a_i+b_i$ 轮流取。
从直接代数的角度上理解,如果 $a_i+b_i\ge a_j+b_j$,则有 $a_i-b_j\ge a_j-b_i$,对后手同理,先取 $i$ 一定不劣。
从更巧妙的构造上来说,把每张照片变成 $(\dfrac{a_i+b_i}{2},\dfrac{a_i+b_i}{2})$,而开始之前先把所有照片的代价加上 $\dfrac{a_i-b_i}{2}$,这样先后手取之后贡献不变,而贪心策略也就很直观了。
回到原来的问题。考虑 $a_{i,1}+b_{i,1}\le a_{i,2}+b_{i,2}$,第一张照片如果本来就要在第二张照片前面取,那么不用管栈的限制。否则:
- 如果 $a_{i,1}\le b_{i,2}$ 且 $b_{i,1}\le a_{i,2}$,则两个人都不取这个。
- 如果 $a_{i,1}\ge b_{i,2}$,则 A 取上面的。
- 如果 $b_{i,1}\ge a_{i,2}$,则 B 取上面的。
排序即可。复杂度 $O(n\log n)$。
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 47 48 49 50 51 52 53 54
| #include<bits/stdc++.h> #define int long long #define ull unsigned long long #define maxn 200005 #define put() putchar('\n') #define Tp template<typename T> #define Ts template<typename T,typename... Ar> using namespace std; Tp void read(T &x){ int f=1;x=0;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();} x*=f; } namespace Debug{ Tp void _debug(char* f,T t){cerr<<f<<'='<<t<<endl;} Ts void _debug(char* f,T x,Ar... y){while(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);} #define gdb(...) _debug((char*)#__VA_ARGS__,__VA_ARGS__) }using namespace Debug; #define fi first #define se second #define mk make_pair const int mod=1e9+7; int power(int x,int y=mod-2) { int sum=1; while (y) { if (y&1) sum=sum*x%mod; x=x*x%mod;y>>=1; } return sum; } int ans,a[maxn],b[maxn],c[maxn],n,cnt; signed main(void){ int i; read(n); for (i=1;i<=n;i++) { read(a[i]);read(b[i]);read(a[i+n]);read(b[i+n]); if (a[i]+b[i]>=a[i+n]+b[i+n]) { c[++cnt]=a[i]+b[i]; c[++cnt]=a[i+n]+b[i+n]; ans+=a[i]-b[i]+a[i+n]-b[i+n]; } else if (a[i]>=b[i+n]) ans+=2*(a[i]-b[i+n]); else if (b[i]>=a[i+n]) ans+=2*(a[i+n]-b[i]); } sort(c+1,c+1+cnt); reverse(c+1,c+1+cnt); for (i=1;i<=cnt;i++) if (i&1) ans+=c[i]; else ans-=c[i]; printf("%lld\n",ans/2); return 0; }
|
总结
这种先手后手问题的策略大概率是严格对称且优雅简洁的。
对称可以理解为先手取完以后后手就变成了先手,不会出现什么“按差值排序一个取最大一个取最小”,因为也要考虑两者相互干扰的情况。
优雅在于不需要管 $\ge$ 还是 $>$,细节不是重点。
贪心策略还是要多积累。