zoukankan      html  css  js  c++  java
  • 【2018.10.15】noip模拟赛Day1

    题面

    wzj的题解

    T1

    随便搜

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 inline int read(){
     5     int x=0; bool f=1; char c=getchar();
     6     for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
     7     for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
     8     if(f) return x;
     9     return 0-x;
    10 }
    11 int T,len;
    12 char c[12];
    13 ll L;
    14 bool dfs2(int wz,ll cur,ll sum,bool Last){
    15     if(!(wz^len)) return sum+cur==L ? 1 : 0;
    16     if(Last==1 && dfs2(wz,0,sum+cur,0)) return 1;
    17     if(dfs2(wz+1,(cur<<3)+(cur<<1)+(c[wz]^'0'),sum,1)) return 1;
    18     return 0;
    19 }
    20 bool dfs(int wz,ll cur,ll sum,bool Last){
    21     if(!(wz^len)) return 0;
    22     if(Last==1){
    23         L=sum+cur;
    24         if(dfs2(wz,0,0,0)) return 1;
    25     }
    26     if(Last==1 && dfs(wz,0,sum+cur,0)) return 1;
    27     if(dfs(wz+1,(cur<<3)+(cur<<1)+(c[wz]^'0'),sum,1)) return 1;
    28     return 0;
    29 }
    30 int main(){
    31     T=read();
    32     while(T--){
    33         scanf("%s",c);
    34         len=strlen(c);
    35         if(dfs(0,0,0,0)) printf("Yes
    ");
    36         else printf("No
    ");
    37     }
    38     return 0;
    39 }
    View Code

    T2

    一道奇怪的题目。

    首先想想dp,不好想。于是推推结论。

    很快发现交换两个数只与以这两个数为两端的区间有关系。

    具体就是说

    你交换红黄两个位置的数,跟红块左边和黄块右边的部分是没有关系的,因为这两块中的0/1与外部的0/1的相对位置没变。

    然后还会发现对于交换的两个数,只有左边是0、右边是1时才有意义,否则可以发现逆序对数不会多,花费也不会少,肯定不优。

    然后左边的0和右边的1交换会增加多少逆序对呢?假设交换的两数的坐标分别为$i,j$,考虑两数中间部分$(i,j)$的取值。

    对于中间所有的0,把1换到前面后它们会各自和前面的1形成一组新的逆序对;

    对于中间所有的1,把0换到后面后它们会各自和后面的0形成一组新的逆序对。

    也就是说,中间部分有多少个数,两端交换后就会出现多少新的逆序对。

    再加上交换的一对0和1又形成一组新的逆序对,一次交换会形成$j-i$组新的逆序对。

    将它和花费$cost_i+cost_j$作差,就得到了对答案的贡献。

    显然,一组交换对答案的贡献 $le 0$ 的话肯定不如不换。

    那如果一组交换对答案的贡献 $gt 0$,交换后一定更优么?

    我们就得考虑交换结果与交换的先后顺序是否有关了。

     

    首先,交换一组数肯定需要$cost_i+cost_j$的花费,有经验的同学会直观感觉这样的交换与先后顺序无关。

    那怎么验证呢?我们取$2$组交换的情况即可。

    1.两组交换区间不相交

    T3

    一眼认数据结构,两眼认线段树,三眼认树状数组。

    一看区间操作机器人位置,那不就是线段树维护每个机器人的坐标了……

    对于1操作,相当于区间赋值,打位置$tag_w$并打个清空子树中所有记录向父亲移动步数的$tag_f$的标记(因为后赋值刷掉前面的移动)。

    对于2操作,跟1差不多,打向父亲移动步数的$tag_f$。

    对于3操作,首先单点查询(查询一个机器人的当前位置),查到那个点的时候,先判断是否要用$tag_w$更新当前机器人在上一次1操作移到的位置,再将其向父亲移动$tag_f$步。

           其次要维护一个子树和。我们可以按dfs序开两个树状数组分别表示 子树所有点的权值和 & 子树内有多少个开灯的点。(其中一个点的权值就是它的深度,它减去另一个点的深度就是两点的距离咯)。

  • 相关阅读:
    ES6 Promise的resolved深入理解
    npm 重点小结
    nodemon 基本配置与使用
    CSS 标准发布流程
    HTML表格基础详解
    <linux/init.h>,<linux/module.h>头文件不存在等问题的解决方法
    libcstl中的list没法插入自定义数据
    Linux下C编写基本的多线程socket服务器
    Linux下C连接MySql数据库
    C++实现最基本的LRUCache服务器缓存
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/2018_10_15.html
Copyright © 2011-2022 走看看