zoukankan      html  css  js  c++  java
  • 「训练日志 20」 6.19 差距

    这次考试题解好像都写在题面上了。。

    贪婪。

    离。

    堆积。

    T1 嚎叫响彻在贪婪的厂房

      等差序列,要保证第i位与第i-1位的差值与之前的所有集合中的数中任意两个相邻数的差值gcd不为1,还有序列中没有重复元素。

      考试的时候想的是分解质因数,然后崩了,又难想又难打。

      其实思路挺简单,实现的话用一个$map$$/$$set$$/$$hash$判重搞定然后没什么了。

      为什么没想到$gcd$呢?还是考试把自己搞死了,自己没想到这一点,只想这分解,最后也没有码出来。

      多方向找性质,不要受局限。

      小弟不才。

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<map>
     4 #include<limits>
     5 #define LL long long 
     6 #define HZOI std
     7 using namespace HZOI;
     8 const int HASH=19260817;
     9 const int Hash=233;
    10 const int N=1e7+3;
    11 LL n,cnt,lst,ans,gcd;
    12 LL a[N];
    13 unsigned LL hs[HASH+3];
    14 map<LL ,bool > mp;
    15 inline void Add(LL ,int );
    16 inline LL Ask(LL );
    17 LL Gcd(LL ,LL );
    18 inline LL read();
    19 inline LL max(LL a,LL b) {return a>b?a:b;}
    20 inline LL min(LL a,LL b) {return a<b?a:b;}
    21 inline LL _abs(LL a) {return a<0?-a:a;}
    22 int main()
    23 {
    24     n=read();
    25     for (int i=1; i<=n; ++i) a[i]=read();
    26     Add(a[1],1),cnt=lst=1;
    27     for (int i=2; i<=n; ++i)
    28     {
    29         if (cnt==1)
    30         {
    31             if (a[i]==a[i-1]) {lst=i;++ans;continue;}
    32             ++cnt,Add(a[i],1);
    33             gcd=_abs(a[i]-a[i-1]);
    34             if (gcd==1)
    35             {
    36                 Add(a[i-1],-1);
    37                 ++ans; lst=i; cnt=1;
    38             }
    39             continue;
    40         }
    41         if (Ask(a[i])) 
    42         {
    43             ++ans;
    44             for (int j=lst; j<i; ++j) Add(a[j],-1);
    45             lst=i, cnt=1, Add(a[i],1);
    46             continue;
    47         }
    48         LL negcd=Gcd(gcd,_abs(a[i]-a[i-1]));
    49         if (negcd<=1)
    50         {
    51             ++ans;
    52             for (int j=lst; j<i; ++j) Add(a[j],-1);
    53             lst=i, cnt=1, Add(a[i],1);
    54             continue;
    55         }
    56         gcd=Gcd(gcd,negcd);
    57         Add(a[i],1),++cnt;
    58     }
    59     printf("%lld
    ",ans+1);
    60 }
    61 LL Gcd(LL a,LL b)
    62 {
    63     if (!b) return a;
    64     return Gcd(b,a%b);
    65 }
    66 inline void Add(LL x,int data)
    67 {
    68     unsigned LL num=x*Hash*Hash*Hash*Hash;
    69     num%=HASH;
    70     hs[num]+=data;
    71 }
    72 inline LL Ask(LL x)
    73 {
    74     unsigned LL num=x*Hash*Hash*Hash*Hash;
    75     num%=HASH;
    76     if (hs[num]>0) return 1;
    77     return 0;
    78 }
    79 inline LL read()
    80 {
    81     LL nn=0; char cc=getchar();
    82     while (cc<'0' || cc>'9') cc=getchar();
    83     while (cc>='0' && cc<='9') nn=(nn<<3)+(nn<<1)+(cc^48),cc=getchar();
    84     return nn;
    85 }
    嚎叫响彻在贪婪的厂房(hash,用map直接替掉hash即可)

    T2 主仆见证了 Hobo 的离别

      咋说呢这题。。

      考试的时候做了个笔记:动态开点权值线段树+树上合并。

      然后我死了。

      “正解”很简单,直接在线算,每次跑一遍Dfs暴力查找两个元素是否在同一条链上,居然能AC跑的还飞快。

      其实真正的正解是离线算法,但我不会,只好水过了。

      不得不说数据太水了。

      小弟不才。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define HZOI std
     4 using namespace HZOI;
     5 const int N=5e6+3;
     6 int n,m;
     7 int dfn[N<<2],low[N<<2];
     8 int tt,first[N<<2],vv[N<<3],nx[N<<3];
     9 int Dfs(int ,int ,int );
    10 inline void Add(int ,int );
    11 inline int read();
    12 int main()
    13 {
    14     n=read(),m=read();
    15     for (int i=1,opt,a,b,c,d; i<=m; ++i)
    16     {
    17         opt=read(),a=read(),b=read();
    18         if (!opt)
    19         {
    20             ++n;
    21             if (b==1) { int x=read(); Add(x,n), Add(n,x); continue;}
    22             if (!a) for (int i=1,x; i<=b; ++i) Add(n,read());
    23             else for (int i=1,x; i<=b; ++i) Add(read(),n);
    24         }
    25         if (opt)
    26         {
    27             if (Dfs(a,0,b)) puts("1");
    28             else puts("0");
    29         }
    30     }
    31 }
    32 int Dfs(int k,int father,int goal)
    33 {
    34     if (k==goal) return 1;
    35     for (int i=first[k]; i; i=nx[i])
    36     {
    37         int ver=vv[i];
    38         if (ver==father) continue;
    39         if (Dfs(ver,k,goal)) return 1;
    40     }
    41     return 0;
    42 }
    43 inline void Add(int u,int v)
    44 {
    45     vv[++tt]=v,nx[tt]=first[u],first[u]=tt;
    46 }
    47 inline int read()
    48 {
    49     int nn=0; char cc=getchar();
    50     while (cc<'0' || cc>'9') cc=getchar();
    51     while (cc>='0' && cc<='9') nn=(nn<<3)+(nn<<1)+(cc^48),cc=getchar();
    52     return nn;
    53 }
    主仆见证了 Hobo 的离别

    T3 征途堆积出友情的永恒

      这道题就有点水平了。

      dp很好打,$dp_i=min(dp_j+max(b_j,sum_i-sum_j))$

      含义不难理解,考虑优化。

      我们发现$dp_j+b_j$是一个定值,所以我们只要选取其最小的就可以了,而$dp_j-sum_j+sum_i$随$i$单调递增,考虑用既然题目上都说了用堆优化,两个堆,一个维护$dp_i+b_i$,第二个维护$dp_i-sum_i$,然后乱搞就好了。

      堆一的弹出条件:1.堆顶元素花费大于其位置为$sum$的花费 2.堆顶元素在范围内。

      开搞,把堆一中元素弹走后,由二接受,然后就可以了,注意判断可行条件

      小弟不才。

      

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 using namespace std;
     5 const int maxn=500005;
     6 #define ll long long
     7 int n,k;
     8 ll  f[maxn],sum[maxn];
     9 int a[maxn],b[maxn];
    10 struct Binary_heap{
    11     ll top,heap[maxn],pn[maxn];
    12     int topp(){  return pn[1];  }
    13     void swap(ll &x,ll &y){ x^=y,y^=x,x^=y; }
    14     void up(int p){
    15         while(p>1){
    16             if(heap[p]<heap[p>>1])  swap(heap[p],heap[p>>1]),swap(pn[p],pn[p>>1]);
    17             else break;   p>>=1;
    18         }
    19     }
    20     void down(int p){
    21         int turn=p<<1;
    22         while(turn<=top){
    23             if(turn<top&&heap[turn]>heap[turn+1])  ++turn;
    24             if(heap[p]>heap[turn]) swap(heap[turn],heap[p]),swap(pn[p],pn[turn]);
    25             else break;    p=turn,turn<<=1;
    26         }
    27     }
    28     void insert(ll x,int y){heap[++top]=x; pn[top]=y; up(top); }
    29     void pop(){ heap[1]=heap[top]; pn[1]=pn[top--]; down(1); }
    30 }fir,sec;
    31 inline int read()
    32 {    
    33     int t=0; char ch=getchar();    
    34     while(ch<'0'||ch>'9')  ch=getchar();
    35     while(ch>='0'&&ch<='9')  t=(t<<3)+(t<<1)+(ch^48),ch=getchar();
    36     return t;
    37 }
    38 int main()
    39 {
    40     n=read(),k=read();
    41     for(register int i=1;i<=n;++i)  a[i]=read(),sum[i]=sum[i-1]+a[i];
    42     for(register int i=0;i<n;++i)  b[i]=read();
    43     ll tf,ts,turn;
    44     memset(f,0x7f,sizeof(f));
    45     f[0]=0;    
    46     fir.insert(b[0],0);
    47     for(register int i=1;i<=n;++i){
    48         turn=max(0,i-k);
    49         while(1){
    50             if(fir.top) tf=fir.topp(); else tf=-1;
    51             if(sec.top) ts=sec.topp();  else ts=-1;
    52             while(fir.top&&tf<turn) fir.pop(),tf=fir.topp();
    53             while(sec.top&&ts<turn) sec.pop(),ts=sec.topp();
    54             if(!fir.top)  tf=-1;  if(!sec.top)  ts=-1;
    55             if(ts!=-1&&(tf==-1||f[ts]-sum[ts]+sum[i]<f[tf]+b[tf])){
    56                 f[i]=f[ts]-sum[ts]+sum[i]; break;
    57             }
    58             if(b[tf]>=sum[i]-sum[tf]){ f[i]=f[tf]+b[tf]; break; }
    59             while(fir.top&&b[tf]<sum[i]-sum[tf]){  sec.insert(f[tf]-sum[tf],tf),fir.pop(),tf=fir.topp(); }
    60         }
    61         fir.insert(f[i]+b[i],i);
    62     }
    63     printf("%lld",f[n]);
    64 }
    征途堆积出友情的永恒
  • 相关阅读:
    线程池中的scheduleAtFixedRate scheduleWithFixedDelay区别
    几道MySQL问题
    【SQL server 2012】复制数据库到另一台机器上
    LeetCode 98. 验证二叉搜索树
    深度学习知识点
    Graph Network Notes
    剑指 Offer 33. 二叉搜索树的后序遍历序列
    剑指 Offer 29. 顺时针打印矩阵
    LeetCode 54. 螺旋矩阵
    LeetCode 50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/LH-Xuanluo/p/11380803.html
Copyright © 2011-2022 走看看