CF2064E Mycraft Sand Sort

第一次一眼秒了一道 E,但是被人均六分钟 C 题硬控一小时,未能写完,遗憾离场,特此纪念。

考虑第一列,无论排列 \(p'\) 是什么样子,第一列一定是 \(c'\)。因此,\(c'\) 数组一定等于 \(c\) 数组。

这个结论还引出一个推论,\(p'\) 一定由 \(p\) 中颜色相同的位置交换得到。如果异色交换,一定会有一种颜色的方块总数变化,此时一定不与初始状态相同。

那我们先考虑一种颜色。一种颜色某个元素可以邻项交换的条件是这两个元素之间的位置大小必须都小于这个位置的大小。手玩一下充分性是显然的,考虑之间的位置大小大于的情况一定会导致某两个方块颜色改变,所以也是必要的。

那么,一个元素可以交换的位置是一段连续的区间,即左右都到第一个大于这个元素的异色位置。这种计数问题的经典做法是先考虑最紧的限制。我们先考虑最小的元素,从小到大依次安排位置。当我们安排一个更大的元素时,这个元素的区间要么和之前的区间无交,要么完全包含。我们把占位置的贡献挂到每段可行区间的左端点,统计有多少个位置已经被占只需要查询可行区间的区间和即可。

然后我们发现每种颜色是独立的,我们先交换小的元素,这样就不会被后来交换的元素影响,一定存在方案。直接乘起来就行了。

上面提到的东西都可以使用线段树维护,使用普通二分时间复杂度 \(O(n\log^2 n)\),使用线段树二分时间复杂度 \(O(n\log n)\)。

#include <bits/stdc++.h>
#define lc(x) ((x)<<1)
#define rc(x) ((x)<<1)|1
using namespace std;
struct node
{
long long mx,sum;
}tr1[1200000],tr2[1200000];
long long t,n,p[300000],c[300000],rt=1;
vector<long long>a[300000];
pair<long long,long long>b[300000];
const long long mod=998244353;
void pushup(struct node tr[],long long x)
{
tr[x].mx=max(tr[lc(x)].mx,tr[rc(x)].mx);
tr[x].sum=tr[lc(x)].sum+tr[rc(x)].sum;
} void build1(long long x,long long l,long long r)
{
tr1[x].mx=tr1[x].sum=0;
if(l==r)
{
tr1[x].mx=p[l];
return;
}
long long mid=(l+r)>>1;
build1(lc(x),l,mid),build1(rc(x),mid+1,r);
pushup(tr1,x);
} long long query1(long long x,long long l,long long r,long long lx,long long rx)
{
if(lx>rx)return 0;
if(l>=lx&&r<=rx)return tr1[x].mx;
long long mid=(l+r)>>1,ans=0;
if(lx<=mid)ans=max(ans,query1(lc(x),l,mid,lx,rx));
if(rx>=mid+1)ans=max(ans,query1(rc(x),mid+1,r,lx,rx));
return ans;
} void build2(long long x,long long l,long long r,long long c)
{
tr2[x].mx=tr2[x].sum=0;
if(l==r)
{
tr2[x].mx=query1(rt,1,n,a[c][l-1]+1,a[c][l]-1);
return;
}
long long mid=(l+r)>>1;
build2(lc(x),l,mid,c),build2(rc(x),mid+1,r,c);
pushup(tr2,x);
} void add(long long x,long long l,long long r,long long p,long long k)
{
if(l==r)
{
tr2[x].sum+=k;
return;
}
long long mid=(l+r)>>1;
if(p<=mid)add(lc(x),l,mid,p,k);
else add(rc(x),mid+1,r,p,k);
pushup(tr2,x);
} long long query2(long long x,long long l,long long r,long long lx,long long rx)
{
if(lx>rx)return 0;
if(l>=lx&&r<=rx)return tr2[x].mx;
long long mid=(l+r)>>1,ans=0;
if(lx<=mid)ans=max(ans,query2(lc(x),l,mid,lx,rx));
if(rx>=mid+1)ans=max(ans,query2(rc(x),mid+1,r,lx,rx));
return ans;
} long long query3(long long x,long long l,long long r,long long lx,long long rx)
{
if(lx>rx)return 0;
if(l>=lx&&r<=rx)return tr2[x].sum;
long long mid=(l+r)>>1,ans=0;
if(lx<=mid)ans=ans+query3(lc(x),l,mid,lx,rx);
if(rx>=mid+1)ans=ans+query3(rc(x),mid+1,r,lx,rx);
return ans;
} int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)a[i].clear(),a[i].push_back(0);
for(int i=1;i<=n;i++)scanf("%lld",&p[i]);
for(int i=1;i<=n;i++)scanf("%lld",&c[i]),a[c[i]].push_back(i);
build1(rt,1,n);
long long ans=1;
for(int i=1;i<=n;i++)
if(a[i].size()>1)
{
long long w=a[i].size()-1;
build2(rt,1,w,i);
for(int j=1;j<=w;j++)b[j].first=p[a[i][j]],b[j].second=j;
sort(b+1,b+w+1);
for(int j=1;j<=w;j++)
{
long long l=1,r=b[j].second-1,lx=r+1,rx=r+1;
while(l<=r)
{
long long mid=(l+r)>>1;
if(query2(rt,1,w,mid+1,b[j].second)<b[j].first)lx=mid,r=mid-1;
else l=mid+1;
}
l=b[j].second+1,r=w;
while(l<=r)
{
long long mid=(l+r)>>1;
if(query2(rt,1,w,b[j].second+1,mid)<b[j].first)rx=mid,l=mid+1;
else r=mid-1;
}
ans=ans*(rx-lx+1-query3(rt,1,w,lx,rx))%mod,add(rt,1,w,lx,1);
}
}
printf("%lld\n",ans%mod);
}
return 0;
}

CF2064E Mycraft Sand Sort 题解的更多相关文章

  1. codechef Turbo Sort 题解

    Input t – the number of numbers in list, then t lines follow [t <= 10^6].  Each line contains one ...

  2. 洛谷 P2945 [USACO09MAR]沙堡Sand Castle 题解

    题目传送门 大概思路就是把这两个数组排序.在扫描一次,判断大小,累加ans. #include<bits/stdc++.h> using namespace std; int x,y,z; ...

  3. LuoguP7259 [COCI2009-2010#3] SORT 题解

    Content 请编写一个"频率排序器".输入一个 长度为 \(n\) 的数列 \(A=\{a_1,a_2,\dots,a_n\}\),要求: 按照每个数的出现次数降序排列. 如果 ...

  4. HDU 1425 sort 题解

    选择出数列中前k个最大的数. 这里由于数据特殊.所以能够使用hash表的方法: #include <cstdio> #include <algorithm> #include ...

  5. Hdoj 1425.sort 题解

    Problem Description 给你n个整数,请按从大到小的顺序输出其中前m大的数. Input 每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含 ...

  6. Insertion Sort List Leetcode java

    题目: Sort a linked list using insertion sort. 题解: Insertion Sort就是把一个一个元素往已排好序的list中插入的过程. 初始时,sorted ...

  7. 【leetcode刷题笔记】Insertion Sort List

    Sort a linked list using insertion sort. 题解:实现链表的插入排序. 要注意的地方就是,处理链表插入的时候尽量往当前游标的后面插入,而不要往前面插入,后者非常麻 ...

  8. 算法与数据结构基础 - 排序(Sort)

    排序基础 排序方法分两大类,一类是比较排序,快速排序(Quick Sort).归并排序(Merge Sort).插入排序(Insertion Sort).选择排序(Selection Sort).希尔 ...

  9. 830. String Sort

    830. String Sort 题解 int alpha[256] = {0};//记录字符的次数 bool cmp(char a,char b) { if(alpha[a]==alpha[b])/ ...

  10. 【AtCoder】ARC088

    C - Multiple Gift 题解 首项是X,每次乘个2,暴力统计 代码 #include <bits/stdc++.h> #define fi first #define se s ...

随机推荐

  1. java一个校验对象是否为null的豪华大礼包

    自写的校验所有类型是否为null的工具类, 懒人福音,嘎嘎好用. 1 /** 2 * 一个校验对象是否为null的豪华大礼包 3 * 可以校验:Collection,Map,String,Enumer ...

  2. Flowable快速入门

    flowable官方文档       官网:https://tkjohn.github.io/flowable-userguide/#_getting_started 工作流(Workflow),是& ...

  3. 探秘Transformer系列之(26)--- KV Cache优化---分离or合并

    探秘Transformer系列之(26)--- KV Cache优化 之 PD分离or合并 目录 探秘Transformer系列之(26)--- KV Cache优化 之 PD分离or合并 0x00 ...

  4. Bean注入几种方式 (放入Spring容器)

    目录 1.XML方式注入 set方式注入 构造方法注入 2.注解方式注入 @Component + @ComponentScan @Configuration + @Bean + @Component ...

  5. ConcurrentHashMap(JDK1.8)put分析

    一.ConcurrentHashMap整体结构 ConcurrentHashMap的数据结构与HashMap差不多,都是Node数组+红黑树+链表:ConcurrentHashMap中table的节点 ...

  6. Google Adsense中文设置

    1. 入口 https://www.google.com/adsense 2. 菜单 Account -> settings -> Personal settings 3. 切换语言 Di ...

  7. Tailwind CSS一些你需要记住的原子类

    前情 Tailwind CSS 是一个原子类 CSS 框架,它将基础的 CSS 全部拆分为原子级别.它的工作原理是扫描所有 HTML 文件.JavaScript 文件以及任何模板中的 CSS 类名,然 ...

  8. 备份一个 VirtualizingWrapPanel ,支持虚拟化

    1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4 using System.Linq; ...

  9. Email邮箱验证码发送

    以下文件保存到/static/email.txt <!DOCTYPE html> <html lang="en" xmlns:th="http://ww ...

  10. Cline技术分析:prompt如何驱动大模型对本地文件实现自主变更

    prompt如何驱动大模型对本地文件实现自主变更 在AI技术快速发展的今天,编程方式正在经历一场革命性的变革.从传统的"人写代码"到"AI辅助编程",再到&qu ...