LOJ#3175. 「IOI2019」排列鞋子 贪心+树状数组
手画一下发现最优策略是统一向左/向右移,那我们就让鞋子向左移.
因为一个鞋子向左移不会使右面的答案变差,而最左面没有被匹配的鞋子也迟早要和一个鞋子去匹配.
写了一个 的暴力,过掉了 50pts.
然后我们发现将鞋子从 移到 的代价是 中已经移到左面的个数.
维护 中移到左面的个数可以用树状数组/线段树.
code:
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 | #include <cstdio> #include <vector> #include <cstring> #include <algorithm> #define N 200009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n; int a[N],c[N],mark[N]; inline int lowbit( int x) { return x&(-x); } void update( int x, int v) { for (;x<N;x+=lowbit(x)) c[x]+=v; } int query( int x) { int tmp=0; for (;x;x-=lowbit(x)) tmp+=c[x]; return tmp; } int ask( int l, int r) { return query(r)-query(l-1); } int pos[100003][2]; vector< int >ar[100003][2]; int main() { // setIO("input"); scanf ( "%d" ,&n),n<<=1; for ( int i=1;i<=n;++i) { scanf ( "%d" ,&a[i]); ar[ abs (a[i])][a[i]>0].push_back(i); } for ( int i=1;i<=(n>>1);++i) { sort(ar[i][0].begin(),ar[i][0].end()); sort(ar[i][1].begin(),ar[i][1].end()); } ll ans=0; for ( int i=1;i<=n;++i) { if (mark[i]) continue ; int flag=a[i]>0; int p=ar[ abs (a[i])][flag^1][pos[ abs (a[i])][flag^1]]; ans+=p-i-1-ask(i,p); update(p,1); mark[p]=1; if (flag==1) ++ans; ++pos[ abs (a[i])][flag^1]; ++pos[ abs (a[i])][flag]; } printf ( "%lld\n" ,ans); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· golang自带的死锁检测并非银弹
· 一个适用于 .NET 的开源整洁架构项目模板
· AI Editor 真的被惊到了
· API 风格选对了,文档写好了,项目就成功了一半!
· 【开源】C#上位机必备高效数据转换助手
· .NET 9.0 使用 Vulkan API 编写跨平台图形应用