• [考试反思]1024csp-s模拟测试85:以为


    愈发垃圾。

    T1基本全场切(除了RP<-inf的zkt和把人擦)

    然后T2想了半天逐渐趋近于正解,但是因为数据有问题锅了25分,没什么好说的。
    T3连题意转化都没有完成。括号匹配转为+1/-1做法都看过多少次了,还不会。。。

    一定要吸取以往的经验,不要让时间空过

    还有今天下午改题速度也非常慢。主要是T3。

    挂了一个微小的不容易(但不是不会)出锅的细节,调了两个多小时。

    我以为那么打没有问题,但是其实考虑的并不周密。

    不要想当然,打代码要的是精密,而不是精妙。

    在打下每一个字之前,考虑好你要为它付出的代价。

    感谢这错误没有出现在考试,感谢它没有毁掉我的CSP-S。

    最近还是那么菜,简单题差不多能拿到手了,难题什么都想不出来。

    其实也是不够认真不够专注吧。。。

    嗯,还有22天。

    T1:表达式密码

    在符号后的两个0之间填加号。在-xx的两个数字之间填加号。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 char s[100005];int n;
     6 int main(){
     7     scanf("%s",s+1);
     8     n=strlen(s+1);
     9     for(int i=1;i<=n;++i){
    10         putchar(s[i]);
    11         if(isdigit(s[i])&&s[i-1]=='-'&&isdigit(s[i+1]))putchar('+'),s[i]='+';
    12         if(s[i]=='0'&&!isdigit(s[i-1])&&isdigit(s[i+1]))putchar('+'),s[i]='+';
    13     }puts("");
    14 }
    View Code

    T2:电压机制

    奇环上的额点必选,偶环上的不能选。

    老套路,图不会做就建一个树,考虑非树边。

    其实dfs得到的树所剩下的边一定是返祖边,所以不用求LCA。

    树上差分,就没了。

    数据问题:不保证联通

     1 #include<cstdio>
     2 int fir[100005],cnt=1,l[400005],to[400005],in[200005],n,m;
     3 int w[100005],x[100005],lim,al[100005],dep[100005],ans;
     4 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
     5 void dfs(int p){//printf("%d
    ",p);
     6     al[p]=1;
     7     for(int i=fir[p];i;i=l[i])if(!al[to[i]])
     8         in[i>>1]=1,dep[to[i]]=dep[p]+1,dfs(to[i]);
     9 }
    10 void DFS(int p){
    11     al[p]=2;
    12     for(int i=fir[p];i;i=l[i])if(al[to[i]]!=2)
    13         DFS(to[i]),w[p]+=w[to[i]],x[p]+=x[to[i]];
    14 }
    15 int main(){//freopen("voltage.in","r",stdin);
    16     scanf("%d%d",&n,&m);
    17     for(int i=1,a,y;i<=m;++i)scanf("%d%d",&a,&y),link(a,y),link(y,a);
    18     dfs(1);
    19     for(int i=1;i<=m;++i)if(!in[i]){
    20         int a=to[i<<1],b=to[i<<1|1];
    21         if(dep[a]+dep[b]&1)
    22             if(dep[a]<dep[b])x[b]++,x[a]--;
    23             else x[a]++,x[b]--;
    24         if(dep[a]+dep[b]&1^1)
    25             if(dep[a]<dep[b])w[a]--,w[b]++,lim++;
    26             else w[a]++,w[b]--,lim++;
    27     }DFS(1);
    28     if(lim==1)ans++;
    29     for(int i=2;i<=n;++i)if(al[i])if(x[i]==0&&w[i]==lim)ans++;
    30     printf("%d
    ",ans);
    31 }
    View Code

    T3:括号密码

    首先,括号匹配的题转化为+1/-1问题,这已经是常用套路了,左加右减。

    问题变为:使每一个子区间[l,r]的前缀和值sum满足sum[r]=sum[l-1]且对于任意$iin [l,r]$有sum[i]>=sum[l-1]

    先不考虑重叠和包含,只考虑若干个区间彼此无交集。

    那么对于每一个区间,如果总的“(”和“)”不一样,那么就要把外面的括号和内部的交换。

    设a[i]表示第i个子区间的总值(前缀和)。如果它是奇数那么无解,否则它就需要从外界得到a[i]/2个右括号。

    如果是负的,那么就要换来左括号。

    然而其实不值得每个区间都付出这么多的代价,因为A区间需要左括号而B区间需要右括号,那么它两个之间互换就好了。

    这样的话我们对于需要左括号的区间付出相应的代价,而对于需要右括号的区间不再付出代价,这样我们就节约了费用。

    但是还没有完,如果所有子区间所索要的左括号与右括号数量不相等,那么就要与非选中区间的地方进行交换。

    如果与外界交换的是左括号,那么没有代价,因为上面已经支付过了。

    如果是右括号的需求更多,那么要再付出额外的代价。

    要注意,如果所有选中的子区间外的括号不够用,那么无解。

    现在我们成功地使每个子区间内部的和为0了,问题在于内部的前缀和可能小于0了。

    所以找到每个子区间最小的前缀和,如果等于0那么就没有关系内部已经合法(当然不会大于0啊)

    如果小于0的话那么你就需要内部调整,调整的代价为w/2,你只需要把最靠右的w/2个'('和最靠左的w/2个')'互换就可以合法了。

    这样我们就计算完代价了。

    如果考虑区间有交集但是不包含呢?

    若[l1,r1]和[l2,r2]分别合法且l1<l2,l2<=r1,r1<r2,那么我们可以根据区间2合法知道交集的最小前缀和为0,这样的话它的总和大于等于0。

    但是如果它大于0的话,[l1,l2-1]这一段就必须小于0,不可能合法,所以[l2,r1]这一段的总和为0。

    这样的话[l1,l2-1],[r1+1,r2]这两部分的总和/最小前缀和也为0。

    所以我们就把这个区间拆成了[l1,l2-1][l2,r1][r1+1,r2]3部分。拆完之后区间就没有重叠关系,就可以按照上面的做了。

    再考虑如何处理包含关系。

    如果区间A包含区间B,那么B的总和和最小前缀和就必须是0。这样的话我们考虑A-B区间和A区间是完全等价的。

    所以在统计A区间的a数组和w数组的时候直接跳过B区间统计过的部分,答案不变。

    所以在你统计的时候把你统计到的部分打标记,以后遇到标记就直接跳过就好了。

    但是当包含和重叠关系同时出现时,要先处理重叠,不然的话会导致统计错误。

     1 #include<cstdio>
     2 #include<algorithm>
     3 struct Q{
     4     int l,r;
     5     friend bool operator<(Q a,Q b){return a.r-a.l<b.r-b.l;}
     6 }q[6005];
     7 int n,w[6005],a[6005],ans,tot,al[2005],Lc,Rc;char s[2055];
     8 int main(){
     9     scanf("%s%d",s+1,&n);
    10     for(int i=1;i<=n;++i)scanf("%d",&q[i].l),q[i].l++;
    11     for(int i=1;i<=n;++i)scanf("%d",&q[i].r),q[i].r++;
    12     for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
    13         if(q[i].l<q[j].l&&q[j].l<=q[i].r&&q[i].r<q[j].r)
    14             q[++n].r=q[j].r,q[n].l=q[i].r+1,q[j].r=q[i].r,q[i].r=q[j].l-1;
    15         else if(q[j].l<q[i].l&&q[i].l<=q[j].r&&q[j].r<q[i].r)
    16             q[++n].r=q[i].r,q[n].l=q[j].r+1,q[i].r=q[j].r,q[j].r=q[i].l-1;
    17     std::sort(q+1,q+1+n);
    18     for(int i=1;i<=n;++i)for(int j=q[i].l;j<=q[i].r;++j)if(!al[j])
    19         a[i]+=(s[j]=='('?1:-1),w[i]=a[i]<w[i]?a[i]:w[i],al[j]=1;
    20     for(int i=1;s[i];++i)if(!al[i])if(s[i]=='(')Lc++;else Rc++;
    21     for(int i=1;i<=n;++i)if(a[i]&1)return puts("-1"),0;else tot+=a[i]>>1;
    22     for(int i=1;i<=n;++i)if(a[i]>0)ans+=a[i]>>1;else w[i]-=a[i];
    23     for(int i=1;i<=n;++i)if(w[i]<0)ans-=w[i]>>1;
    24     if(tot<-Lc||tot>Rc)return puts("-1"),0;
    25     printf("%d
    ",ans-(tot<0?tot:0));
    26 }
    View Code
  • 相关阅读:
    Wireshark的简介
    Node.js + Express 构建的订餐系统
    java 文件下载支持中文名称
    java判断A字符串中是否包含B字符
    Java查询目录下的所有文件(包括子目录)
    Java从指定URL下载文件并保存到指定目录
    Java逻辑分页代码
    JS实现文字向上无缝滚动轮播
    JAVA调用外部安装7-Zip压缩和解压zip文件
    Zip文件和RAR文件解压
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11733929.html
Copyright © 2020-2023  润新知