• [考试反思]1002csp-s模拟测试56:凌乱


    放假回来状态回升??(玩够了~但是稍困)

    T1打的不完全对,但是过掉了。很快的想到了二分吧喇叭啦。。

    然后T2也挺快想出来了但是挂细节没发现,考试快结束的时候才发现出锅了。

    改了过来是正解,但是出题人无良卡了线段树强制树状数组,T了一个子任务,卡常到飞起。

    T3暴力没什么问题。

    卡常是一种习惯。要注意题目数据范围观察是否卡常。

    T1:Merchant

    所有的决策都是一条一次函数。

    分两类,斜率正或斜率非负。

    如果第二类的直线里有在T=0时符合要求的,那么答案就是0,所以check(0)一下。

    如果非负的直线都在T=0时不符合要求,那么以后这些直线都不符合要求了。

    所以排除,只剩下斜率为正的直线了,它们到底什么时候符合要求?

    因为斜率都是正的,那么现在符合要求以后也一定符合,满足单调性。

    二分。贪心。nth_element(sort被卡复杂度)。

    注意判断价值为负的物品不选,而不是一定选满m个。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 #define int long long
     5 int n,m,S,k[1000005],b[1000005],res[1000005];
     6 bool chk(int tim){int tot=0;//printf("%lld ",tim);
     7     for(int i=1;i<=n;++i)res[i]=k[i]*tim+b[i];
     8     nth_element(res+1,res+n-m+1,res+n+1);
     9     for(int i=n-m+1;i<=n;++i)if(res[i]>=0){tot+=res[i];if(tot>=S)return true;}//printf("%lld %lld
    ",tot,S);
    10     return tot>=S;
    11 }
    12 main(){//freopen("merchant3.in","r",stdin);
    13     scanf("%lld%lld%lld",&n,&m,&S);//printf("%lld %lld
    ",n,m);
    14     for(int i=1;i<=n;++i)scanf("%lld%lld",&k[i],&b[i]);
    15     int l=0,r=1000000000;
    16     while(l<r-1)if(chk(l+r>>1))r=l+r>>1;else l=(l+r>>1)+1;
    17     printf("%lld
    ",chk(l)?l:r);
    18 }
    View Code

    同理可证总决策线是个单谷函数。

    思路积累:

    • 分类讨论:直线斜率的正负。

    T2:Equation

    因为是一棵树,设根的权值为x,那么每个点的权值都可以根据路径上的方程来表示为含x的式子:x+a或a-x。a是常数

    然后对于询问,分类讨论解方程即可。

    对于修改,子树内的点的表达式都有变化。

    可以发现,深度为奇数的点都是加,偶数的点都是减。

    第一想法是线段树,直接子树加,在叶节点特殊处理加减即可。

     1 #include<cstdio>
     2 int n,q,dep[1000005],f[1000005],w[1000005],W[1000005],tim,re[1000005];
     3 int fir[1000005],l[1000005],to[1000005],cnt,dfn[1000005],rdfn[1000005];
     4 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
     5 void dfs(int p){
     6     dep[p]=dep[f[p]]+1;w[p]=W[p]-w[f[p]];dfn[p]=++tim;re[tim]=p;
     7     for(int i=fir[p];i;i=l[i])dfs(to[i]);rdfn[p]=tim;
     8 }
     9 struct Segment_Tree{
    10     int cl[4000005],cr[4000005],tw[4000005],lz[4000005];
    11     void build(int l,int r,int p=1){
    12         cl[p]=l;cr[p]=r;
    13         if(l==r){tw[p]=w[re[l]];return;}
    14         build(l,l+r>>1,p<<1);build((l+r>>1)+1,r,p<<1|1);
    15     }
    16     void down(int p){
    17         tw[p<<1]+=lz[p]*((dep[re[cl[p<<1]]]&1)?1:-1);
    18         tw[p<<1|1]+=lz[p]*((dep[re[cl[p<<1|1]]]&1)?1:-1);//printf("down:%d %d
    ",re[cl[p<<1]],re[cr[p<<1|1]]);
    19         lz[p<<1]+=lz[p];lz[p<<1|1]+=lz[p];
    20         lz[p]=0;
    21     }
    22     void add(int l,int r,int _w,int p=1){//printf("add:%d %d %d
    ",p,cl[p],cr[p]);
    23         if(l<=cl[p]&&cr[p]<=r){lz[p]+=_w;tw[p]+=_w*((dep[re[cl[p]]]&1)?1:-1);return;}
    24         if(lz[p])down(p);
    25         if(l<=cr[p<<1])add(l,r,_w,p<<1);
    26         if(r>=cl[p<<1|1])add(l,r,_w,p<<1|1);
    27     }
    28     int ask(int pos,int p=1){
    29         if(cl[p]==cr[p])return tw[p];
    30         if(lz[p])down(p);
    31         return pos<=cr[p<<1]?ask(pos,p<<1):ask(pos,p<<1|1);
    32     }
    33 }T;
    34 int main(){
    35     scanf("%d%d",&n,&q);
    36     for(int i=2;i<=n;++i)scanf("%d%d",&f[i],&W[i]),link(f[i],i);
    37     dfs(1);T.build(1,n);//for(int i=1;i<=n;++i)printf("%d ",w[i]);
    38     for(int i=1,opt,u,v,ww;i<=q;++i){
    39         scanf("%d",&opt);
    40         if(opt==1){
    41             scanf("%d%d%d",&u,&v,&ww);int Q=T.ask(dfn[u])+T.ask(dfn[v]);//printf("%d %d
    ",T.ask(dfn[u]),T.ask(dfn[v]));
    42             if(dep[u]&1^dep[v]&1)puts(Q==ww?"inf":"none");
    43             else if(Q-ww&1)puts("none");
    44             else if(dep[u]&1)printf("%d
    ",ww-Q>>1);
    45             else printf("%d
    ",Q-ww>>1);
    46         }else scanf("%d%d",&u,&ww),T.add(dfn[u],rdfn[u],(ww-W[u])*((dep[u]&1)?1:-1)),W[u]=ww;
    47     }
    48 }
    T86

    那么考虑如何用树状数组来维护。

    区间加,单点查询。树状数组不能直接做,所以要差分。

    根据度数奇偶加减不同,那么如果我们把度数为奇数的点都取相反数。

    取出来的时候再相反数一下就好了。

     1 #include<cstdio>
     2 #define int long long
     3 int dep[1000005],f[1000005],w[1000005],W[1000005],tim,re[1000005],n;
     4 int fir[1000005],l[1000005],to[1000005],cnt,dfn[1000005],rdfn[1000005];
     5 inline void link( int a, int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
     6 const int L=1<<20|1;
     7 char buffer[L],*S,*TT;
     8 #define getchar() ((S==TT&&(TT=(S=buffer)+fread(buffer,1,L,stdin),S==TT))?EOF:*S++)
     9 const int maxn=100000+5;
    10 inline int read(register int &p,register int nt=1,register char ch=getchar()){p=0;
    11     while(ch>'9'||ch<'0'){if(ch=='-')nt=-1;ch=getchar();}
    12     while(ch<='9'&&ch>='0')p=(p<<3)+(p<<1)+ch-48,ch=getchar();p*=nt;
    13 }
    14 void dfs(int p){
    15     dep[p]=dep[f[p]]^1;w[p]=W[p]-w[f[p]];dfn[p]=++tim;re[tim]=p;
    16     for(int i=fir[p];i;i=l[i])dfs(to[i]);rdfn[p]=tim;
    17 }
    18 struct Tree_Array{
    19     int t[1000005];
    20     inline void ADD(int p,int w){for(;p<=1000000;p+=p&-p)t[p]+=w;}
    21     inline int SUM(int p,int a=0){for(;p;p^=p&-p)a+=t[p];return a;}
    22     inline void add(int L,int R,int w){ADD(L,w);ADD(R+1,-w);}
    23     inline int ask(int p){return SUM(p)*(dep[re[p]]?1:-1);}
    24     inline void build(){for(int i=1;i<=n;++i)ADD(i,(w[re[i]]*(dep[re[i]]?1:-1))-(w[re[i-1]]*(dep[re[i-1]]?1:-1)));}
    25 }T;
    26 main(){
    27     int q;scanf("%d%d",&n,&q);
    28     for(int i=2;i<=n;++i)read(f[i]),read(W[i]),link(f[i],i);
    29     dfs(1);T.build();
    30     for(int i=1,opt,u,v,ww;i<=q;++i){
    31         read(opt);
    32         if(opt==1){
    33             read(u);read(v);read(ww); int Q=T.ask(dfn[u])+T.ask(dfn[v]);
    34             if(dep[u]^dep[v])puts(Q==ww?"inf":"none");
    35             else if(Q-ww&1)puts("none");
    36             else if(dep[u])printf("%d
    ",ww-Q>>1);
    37             else printf("%d
    ",Q-ww>>1);
    38         }else read(u),read(ww),T.add(dfn[u],rdfn[u],(ww-W[u])*(dep[u]?1:-1)),W[u]=ww;
    39     }
    40 }
    View Code

    思路积累:

    • 树状数组维护特殊操作:存相反数

    T3:

    还在改。咕。。。


    其实不是不会写而咕。

    但是第二机房实在是太颓了。。。效率超低。。。

    一下午基本什么都没干。。

    再不回去我可能就要毁了。。。

    但是看现在这个总分好像还是很悬啊。。。

    我想回去。。。


  • 相关阅读:
    windows多线程(三) 原子操作
    windows多线程(二) 等待线程返回
    windows多线程(一) 创建线程 CreateThread
    Js 中的原始值和引用值
    Linux 文件系统介绍
    Linux命令(二十) 显示系统内存状态 free
    Linux命令(十九) 查看系统负载 uptime
    Linux命令(十八) 压缩或解压缩文件和目录 gzip gunzip
    git使用
    python 中调用shell命令
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11619250.html
Copyright © 2020-2023  润新知