zoukankan      html  css  js  c++  java
  • Codeforces 1150

    1150 C

    题意

    给你一个由 (1,2) 组成的数组,要你重新排列这个数组,使得它的所有是质数的前缀和最长。 ((1le nle 200000))

    Examples

    input
    5
    1 2 1 2 1
    output
    1 1 1 2 2
    input
    9
    1 1 2 1 1 1 2 1 1
    output
    1 1 1 2 1 1 1 2 1

    一个一个往上去凑就行了,优先选2。

    1150 D

    题意

    给你一个长 (le 10^5) 的文本串,现在你有三个模式串,每个长度 (le 250) ,初始为空,现在你有两种操作:

    • + i c,给串 (i) 末尾加上一个字符 (c)
    • - i,删除 (i) 末尾的字符

    现在在每次操作后询问三个串是否分别对应文本串中三个不相交的子序列

    Examples

    input

    6 8
    abdabc
    + 1 a
    + 1 d
    + 2 b
    + 2 c
    + 3 a
    + 3 b
    + 1 c
    - 2
    

    output

    YES
    YES
    YES
    YES
    YES
    YES
    NO
    YES
    

    input

    6 8
    abbaab
    + 1 a
    + 2 a
    + 3 a
    + 1 b
    + 2 b
    + 3 b
    - 1
    + 2 z
    

    output

    YES
    YES
    YES
    YES
    YES
    NO
    YES
    NO
    

    每次询问可以在 (O(len^2)(lenle 250)) 时间内解决,考虑 (n^2) dp。
    我们设 (nxt[i][c]) 为字符 (c) 在位置 (i) 后第一次出现的位置。
    先考虑 (n^3) 做法。
    (dp[i][j][k]) 表示第一个串匹配到 (i) ,第二个串匹配到 (j) ,第三个串匹配到 (k) ,三个串对应的子序列中末尾最前面的末尾的位置。
    这样的话全部转移是 (n^3) 的。
    但是对于每个询问我们发现只需要用 (n^2) 去更新对应的dp值。
    所以复杂度为 (O(qlen^2))

    1150 E

    题意

    给你一个括号序列,有 (q(le 10^5)) 次操作,每次操作交换两个括号,问每一步操作后括号序列对应的括号树的直径。

    Examples

    input
    5 5
    (((())))
    4 5
    3 4
    5 6
    3 6
    2 5
    output
    4
    3
    3
    2
    4
    4
    input
    6 4
    (((())()))
    6 7
    5 4
    6 4
    7 4
    output
    4
    4
    4
    5
    3

    线段树维护括号区间。
    树的直径其实就是 (max(dep[u]+dep[v]-2*dep[lca(u,v)]))
    对于每一个区间,我们记

    • (delta) 最左侧括号深度 (-) 最右侧括号深度。
    • (mx)(dep[u]) ,最深的节点的深度
    • (m) 即 $$dep[lca]$ ,最浅的节点的深度
    • (lm)(dep[u]-2*dep[lca])
    • (mr)(-2*dep[lca]+dep[v])
    • (lmr)(dep[u]+dep[v]-2*dep[lca])

    询问时询问线段树根节点的 (lmr) 值。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=200003,INF=1050000000;
    struct node{int delta,mx,m,lm,mr,lmr;}t[maxn<<2];
    int n;
    char s[maxn];
    node operator +(node t2,node t3){
    	node t1;
    	t1.delta=t2.delta+t3.delta;
    	t3.mx+=t2.delta;
    	t3.m-=2*t2.delta;
    	t3.lm-=t2.delta;
    	t3.mr-=t2.delta;
    	t1.mx=max(t2.mx,t3.mx);
    	t1.m=max(t2.m,t3.m);
    	t1.lm=max(max(t2.lm,t3.lm),t2.mx+t3.m);
    	t1.mr=max(max(t2.mr,t3.mr),t2.m+t3.mx);
    	t1.lmr=max(max(t2.lmr,t3.lmr),max(t2.mx+t3.mr,t2.lm+t3.mx));
    	return t1;
    }
    void build(int p,int l,int r){
    	if(l==r){
    		t[p].mx=t[p].delta=(s[l]=='('?1:-1);
    		t[p].m=-2*t[p].mx;
    		t[p].lm=t[p].mr=-INF;
    		t[p].lmr=-INF;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);
    	build(p<<1|1,mid+1,r);
    	t[p]=t[p<<1]+t[p<<1|1];
    }
    void change(int p,int l,int r,int pos,char k){
    	if(l==r){
    		int f=(k=='('?2:-2);
    		t[p].delta+=f;
    		t[p].mx+=f;
    		t[p].m-=2*f;
    		t[p].lm-=f;
    		t[p].mr-=f;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(p<<1,l,mid,pos,k);
    	else change(p<<1|1,mid+1,r,pos,k);
    	t[p]=t[p<<1]+t[p<<1|1];
    }
    int query(){
    	return max(t[1].mx,t[1].lmr);
    }
    int main(){
    	int Q;
    	scanf("%d%d%s",&n,&Q,s+1);
    	n=(n-1)<<1;
    	build(1,1,n);
    	printf("%d
    ",query());
    	while(Q--){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		change(1,1,n,x,s[x]=(s[x]=='('?')':'('));
    		change(1,1,n,y,s[y]=(s[y]=='('?')':'('));
    		printf("%d
    ",query());
    	}
    	return 0;
    }
    

    1149 D

    考虑删掉所有的b边,剩下若干个连通块,我们只考虑连接两个不同连通块的b边,最后bfs跑最短路,用状压记录是否已经访问了该连通块。连通块大小 (le 3) 的,不用记到状压里去,手模一下就知道了。然后复杂度就对了。

  • 相关阅读:
    [转] Oracle数据库备份与恢复
    Oracle RMAN 恢复控制文件到指定的路径
    [转] AIX lv 4k偏移量
    关于oracle 10g creating datafile with zero offset for aix
    linux中的chage命令
    [转] Oracle sql 查询突然变慢 -- 案例分析
    [转] Oracle analyze table 使用总结
    [转] Oracle analyze 命令分析
    .net 事务
    _BIN 二进制排序
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10807485.html
Copyright © 2011-2022 走看看