\(T1\)括号序列

——那是,朝思夜想也未尝得到的自由

一个比较常见的转化,考虑如何判断前一段和后一段能够拼成一个合法的括号序列

充要条件:

前半部分,‘(’看为\(1\), ‘)’看为\(-1\),前缀和一直\(\geq 0\)

后半部分,‘)’看为\(1\), '('看做\(-1\),后缀和一直\(\geq 0\)

并且前缀和等于后缀和

然后,依照这个结论可以使用暴力拿到\(70pts\),\(100pts\)需要写的很麻烦,所以换一种写法

\(70pts\):

暴力统计每个位置满足条件的就好了

#include<cstdio>
using namespace std;
int n,q,l,r,cn[8010];
char s[8010];
int main()
{
scanf("%d%d%s",&n,&q,s+1);
for(int i=1;i<=q;i++)
{
scanf("%d%d",&l,&r);
long long res=0;
int li=l-1,lt=0;
while(li<r&&lt>=0)
{
cn[lt]++;
if(s[++li]=='(')lt++;
else lt--;
}
int ri=r+1,rt=0;
while(ri>l&&rt>=0)
{
if(li==ri)
{
if(s[li--]=='(')lt--;
else lt++;
cn[lt]--;
}
res+=cn[rt];
if(s[--ri]==')')rt++;
else rt--;
}
while(li>=l)
{
if(s[li--]=='(')lt--;
else lt++;
cn[lt]--;
}
printf("%lld\n",res);
}
return 0;

设\(f[l][r]\)表示区间\([l,r]\)的方案数

考虑类似\(S[l,r]\)形如\((...)\)的询问,\(l'\)为\(s[l]\)匹配右括号的位置,\(r'\)为\(s[r]\)匹配左括号的位置,我们对删去\(L,R\)位置进行讨论

\(Sit_1:L>l'\)或\(R<r'\)

\(Case_1:L>l'\)且\(R<r'\) \(f[l][r]+=f[l'+1][r'-1]\)比较显然,可以和外面的合法括号序列接上

\(Case_2:R<r',f[l][r]+=f[l][r'-1]\),同上

\(Case_3:L>l' ,f[l][r]+=f[l'+1][r]\),同上

\(Sit_2:L\leq l',R\geq r'\)

\(f[l][r]+=f[l+1][r-1]\)

至于不是形如这样的询问,直接把\(l'=n,r'=1\)即可

正确性的话,这样的话转移的时候不合法的就直接变成\(0\)了,就是包含最左最右不合法部分的

#include<bits/stdc++.h>
#define MAXN 8010
using namespace std;
int n,q,in1,in2,pre[MAXN],nxt[MAXN],dp[MAXN][MAXN];
vector<int>sta;
char s[MAXN];
int main()
{
scanf("%d%d",&n,&q);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
{
pre[i]=1;//r'
nxt[i]=n;//l'
}
for(int i=1;i<=n;i++)
{
if(s[i]=='(')
{
sta.push_back(i);
}
else
{
if(!sta.empty())
{
nxt[sta.back()]=i;
sta.pop_back();
}
}
} sta.clear();
for(int i=n;i;i--)
{
if(s[i]==')')
{
sta.push_back(i);
}
else
{
if(!sta.empty())
{
pre[sta.back()]=i;
sta.pop_back();
}
}
}
sta.clear();
for(int i=1;i<=n;i++)dp[i][i]=1;
for(int i=1;i<n;i++)
{
for(int j=1;j+i<=n;j++)
{
dp[j][j+i]=dp[nxt[j]+1][j+i]+dp[j][pre[j+i]-1]-dp[nxt[j]+1][pre[j+i]-1]+1;
// cout<<"zy: "<<nxt[j]+1<<" "<<j+i<<"\n";
// cout<<"zy: "<<j<<" "<<pre[j+i]-1<<"\n";
// cout<<"zy: "<<nxt[j]+1<<" "<<pre[j+i]-1<<"\n";
if(s[j]=='('&&s[j+i]==')')
{
dp[j][j+i]+=dp[j+1][j+i-1];
}
}
}
for(int i=1,l,r;i<=q;i++)
{
scanf("%d%d",&l,&r);
cout<<dp[l][r]<<"\n";
}
return 0;
}

\(T2\)泽连斯基

——那是,至今为止都不曾体会的懵懂

\(l_i\le r_i\)的部分分比较简单,考虑维护一个单点最大值就好了,因为必然有一个位置被所有线段包含

正解:

考虑枚举一个圆弧,钦定为答案中最短的圆弧为\(x\)

可以把其余圆弧分成\(7\)类

\(Case_1:\)和\(x\)相同,必然需要加入答案

\(Case_2:\)被\(x\)包含,钦定\(x\)最小,必然不选

\(Case_3:\)包含\(x\),由于\(x\)和其他有交,那么包含\(x\)必然也有交,必然加入答案

\(Case_4:\)和\(x\)无交,必然不选

\(Case_5:\)包含\(x\)左端点,称为\(L\),下面讨论

\(Case_6:\)包含\(x\)右端点,称为\(R\),下面讨论

\(Case_7:\)包含左右\(x\)端点,但不包含\(x\),称为\(U\),\(U\)必然与\(L/R\)相交,\(U\)必选

我们只需考虑\(L,R\)最多可以选出几个,\(L,R\)内部必然两两相交

所以我们二维数点!

圆弧看成平面上一个点\((x,y)\),\(L\)为黑点,\(R\)为白点,转化成

平面上选出最多的点使得不存在一个黑点\((x_1,y_1)\)和一个白点\((x_2,y_2)\)满足\(x_1<y_1\land x_2<y_2\)

然后考虑\(dp\),\(f[x][y]\)表示横坐标\(\leq x\)的所有点,黑点纵坐标最小值为\(y\)最多能选多少个,由于最大值我们直接选一个最大值转移就好了,这就变成了一个线段树优化\(DP\)

#include <bits/stdc++.h>
//#define int long long
#define ll long long
#define db double
#define fi first
#define se second
#define pii pair<int,int>
#define vi vector<int> using namespace std;
const int maxn=6e3;
struct node {
int l,r;
} a[maxn+5];
int n,L[maxn+5],R[maxn+5],key[maxn*2+5],cnt,cnt2; int ID[maxn+5],len[maxn+5];
int in(int l,int r,int x) {
if (l<=r) return l<=x && x<=r;
return ((l<=x && x<=cnt) || (1<=x && x<=r));
}
struct point {
int x,y,o;
point() {
x=y=o=0;
}
point(int a,int b,int c) {
x=a,y=b,o=c;
}
bool operator < (const point &t) const {
return x==t.x?(o>t.o):x<t.x;
}
} b[maxn+5];
int num; int mx[maxn*8+5],tag[maxn*8+5];
void seta(int p,int d) {
tag[p]+=d;
mx[p]+=d;
}
void upd(int p) {
mx[p]=max(mx[p+p],mx[p+p+1]);
}
void push(int p) {
if (!tag[p]) return ;
seta(p+p,tag[p]);
seta(p+p+1,tag[p]);
tag[p]=0;
}
void build(int p,int l,int r) {
mx[p]=-1e9;
tag[p]=0;
if (l==r) {
if (l==cnt2) mx[p]=0;
return ;
}
int mid=(l+r)>>1;
build(p+p,l,mid);
build(p+p+1,mid+1,r);
upd(p);
}
void modify(int p,int l,int r,int ql,int qr,int d) {
if (ql>qr) return ;
if (l==ql&&r==qr) {
seta(p,d);
return ;
}
int mid=(l+r)>>1;
push(p);
if (qr<=mid) modify(p+p,l,mid,ql,qr,d);
else if (mid<ql) modify(p+p+1,mid+1,r,ql,qr,d);
else modify(p+p,l,mid,ql,mid,d),modify(p+p+1,mid+1,r,mid+1,qr,d);
upd(p);
}
void cover(int p,int l,int r,int pos,int d) {
if (l==r){
mx[p]=max(mx[p],d);
return ;
}
push(p);
int mid=(l+r)>>1;
if (pos<=mid) cover(p+p,l,mid,pos,d);
else cover(p+p+1,mid+1,r,pos,d);
upd(p);
}
int query(int p,int l,int r,int ql,int qr) {
if (ql>qr) return -1e9;
if (l==ql&&r==qr) return mx[p];
int mid=(l+r)>>1;
push(p);
if (qr<=mid) return query(p+p,l,mid,ql,qr);
else if (mid<ql) return query(p+p+1,mid+1,r,ql,qr);
else return max(query(p+p,l,mid,ql,mid),query(p+p+1,mid+1,r,mid+1,qr));
} void solve() {
cin>>n;
cnt=0;
for (int i=1;i<=n;i++) {
cin>>L[i]>>R[i];
key[++cnt]=L[i],key[++cnt]=R[i];
}
sort(key+1,key+cnt+1);
cnt=unique(key+1,key+cnt+1)-key-1;
for (int i=1;i<=n;i++) {
L[i]=lower_bound(key+1,key+cnt+1,L[i])-key;
R[i]=lower_bound(key+1,key+cnt+1,R[i])-key;
len[i]=(R[i]-L[i]+cnt)%cnt;
}
for (int i=1;i<=cnt;i++) ID[i]=0;
int ans=0;
for (int i=1;i<=n;i++) {
num=cnt2=0;
int nl=L[i],nr=R[i];
int p=nl;
while (1) {
ID[p]=i;
if (p==nr) break ;
p=p%cnt+1;
}
int cursum=0;
for (int j=1;j<=n;j++) {
if (i==j) continue ;
if (len[j]<len[i]) {
continue ;
}
int inl=in(L[j],R[j],L[i]);
int inr=in(L[j],R[j],R[i]);
if (!inl && !inr) continue ;
if (inl && inr) cursum++;
else {
int x=L[j],y=R[j];
if (ID[x]!=i) swap(x,y);
x=(x-L[i]+cnt)%cnt;
y=(L[i]-y+cnt)%cnt;
x++,y++;
if (inl) {
b[++num]=point(x,y,0);
key[++cnt2]=y;
}
else {
b[++num]=point(x,y,1);
key[++cnt2]=y;
}
}
}
if (!num) {
ans=max(ans,cursum+1);
continue;
}
sort(key+1,key+cnt2+1);
cnt2=unique(key+1,key+cnt2+1)-key-1;
for (int j=1;j<=num;j++) {
b[j].y=lower_bound(key+1,key+cnt2+1,b[j].y)-key;
}
build(1,1,cnt2);
sort(b+1,b+num+1);
for (int j=1;j<=num;j++) {
if (b[j].o==0) {
modify(1,1,cnt2,1,b[j].y-1,1);
int mx=query(1,1,cnt2,b[j].y,cnt2);
cover(1,1,cnt2,b[j].y,mx+1);
}
else {
modify(1,1,cnt2,b[j].y,cnt2,1);
}
}
ans=max(ans,cursum+mx[1]+1);
}
cout<<ans<<'\n';
}
int main() { int T;
cin>>T;
while (T--) solve();
return 0;
}

\(T3\)​

——那是,将我们三色交织在一起的绘卷

不会

讲题人:这道题太奇怪了,咱们不讲了吧

魔怔出题人的题解

6.6 NOI 模拟的更多相关文章

  1. 5.30 NOI 模拟

    $5.30\ NOI $模拟 高三大哥最后一次模拟考了,祝他们好运 \(T1\)装箱游戏 显然可以将四种字母之间的空缺当做状态枚举 那么这道题就很显然了 #include<bits/stdc++ ...

  2. 5.23 NOI 模拟

    $5.23\ NOI $模拟 \(T1\)简单的计算几何题 \(zjr:\)我当时没改,那么自己看题解吧 倒是有个简单的随机化方法(能获得\(72pts,\)正确性未知)\(:\) 随机两条切椭圆的平 ...

  3. 5.6 NOI模拟

    \(5.6\ NOI\)模拟 明天就母亲节了,给家里打了个电话(\(lj\ hsez\)断我电话的电,在宿舍打不了,只能用教练手机打了) 其实我不是很能看到自己的\(future,\)甚至看不到高三的 ...

  4. 5.4 NOI模拟

    \(5.4\ NOI\)模拟 \(T1\) 想到分讨,但是暴力输出一下方案之后有很多特别的情况要讨论,就弃了... 假设\(a\)是原序列,\(b\)是我们得到的序列 设\(i\)是最长公共前缀,\( ...

  5. NOI模拟赛 Day1

    [考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...

  6. NOI 模拟赛 #2

    得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...

  7. 【2018.12.10】NOI模拟赛3

    题目 WZJ题解 大概就是全场就我写不过 $FFT$ 系列吧……自闭 T1 奶一口,下次再写不出这种 $NTT$ 裸题题目我就艹了自己 -_-||| 而且这跟我口胡的自创模拟题 $set1$ 的 $T ...

  8. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  9. NOI模拟赛Day5

    T1 有and,xor,or三种操作,每个人手中一个数,求和左边进行某一种运算的最大值,当t==2时,还需要求最大值的个数. test1 20% n<=1000 O(n^2)暴力 test2 2 ...

  10. NOI模拟赛Day4

    看到成绩的时候我的内心** woc第一题写错了呵呵呵呵呵呵呵呵 人不能太浪,会遭报应的** ------------------------------------------------------ ...

随机推荐

  1. 128_Power BI父级排名TOPN子级动态展示

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 前些天在和朋友交流Power BI中有这样一个需求,按照父级排名后,需要显示出父级TOPN的子级明细. 如下&l ...

  2. 分享一个 SpringCloud Feign 中所埋藏的坑

    背景 前段时间同事碰到一个问题,需要在 SpringCloud 的 Feign 调用中使用自定义的 URL:通常情况下是没有这个需求的:毕竟都用了 SpringCloud 的了,那服务之间的调用都是走 ...

  3. 前端向后端传递formData类型的二进制文件

    // 获取到的文件file类型转换为formData类型 let formData = new FormData(); formData.append("file", file文件 ...

  4. 20212115朱时鸿实验一《python程序设计》实验报告

    ------------恢复内容开始------------ #学号20212115 <python程序设计>实验一报告 课程: <python程序设计> 班级:2121 姓名 ...

  5. CF1485E Move and Swap

    题意:Move and Swap 很好的题呢 n个节点的树,根为1,所有叶子的深度都是D,一开始根节点上有两个颜色分别微R,B的球,你执行下列操作D-1次: 1.R点跳到子树内 2.B点跳到下一层的任 ...

  6. 使用 Nocalhost 开发 Rainbond 上的微服务应用

    本文将介绍如何使用 Nocalhost 快速开发 Rainbond 上的微服务应用的开发流程以及实践操作步骤. Nocalhost 可以直接在 Kubernetes 中开发应用,Rainbond 可以 ...

  7. SpringBoot的浅浅配置和小整合

    SpringBoot的浅浅配置和小整合 本文如题,就是浅浅记录一下学习的过程中一些过程,比较简单,并没有多少深度.谢谢! SpringBoot创建 从IDEA中新建项目或者模块.注意jdk版本,一般不 ...

  8. 用Typescript 的方式封装Vue3的表单绑定,支持防抖等功能。

    Vue3 的父子组件传值.绑定表单数据.UI库的二次封装.防抖等,想来大家都很熟悉了,本篇介绍一种使用 Typescript 的方式进行统一的封装的方法. 基础使用方法 Vue3对于表单的绑定提供了一 ...

  9. SAP APO-数据集市,信息多维数据集和Dp

    在SAP Advanced Planning and Optimization中,每个数据集市都包含InfoCube,这些InfoCube存储实际数据和较早的计划数据. 在诸如SAP BW之类的数据仓 ...

  10. SAP Display picture

    program sap_picture_demo. set screen 200. TYPE-POOLS cndp. ***************************************** ...