zoukankan      html  css  js  c++  java
  • noip模拟测试40


    T1:队长快跑

      考虑dp,发现一维无法解决,于是二维做

      $f[i][j]$表示考虑前i个水晶,选择其中一些,且满足$min_A=j$时最多能选的个数

      然后将第一维去掉,对第二维用线段树维护,维护时讨论$A_i$与$B_i$的大小关系即可

      复杂度为$O(nlogn)$

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<algorithm>
      7 using namespace std;
      8 const int MAXN=500233,INF=0x3f3f3f3f;
      9 int n,A[MAXN],B[MAXN],book[MAXN*2],tot;
     10 struct node {
     11     int val,tag,l,r;
     12     node() {
     13         val=tag=l=r=0;
     14     }
     15 }tr[MAXN*4];
     16 void build(int p,int l,int r) {
     17     tr[p].l=l,tr[p].r=r;
     18     if(l==r) return;
     19     int mid=(l+r)>>1;
     20     build(p<<1,l,mid),build(p<<1|1,mid+1,r);
     21 }
     22 void up(int p) {
     23     tr[p].val=max(tr[p<<1].val,tr[p<<1|1].val);
     24 }
     25 void add(int p,int l,int r,int k) {
     26     if(tr[p].l==l&tr[p].r==r) {
     27         tr[p].val+=k,tr[p].tag+=k;
     28         return ;
     29     }
     30     int mid=(tr[p].l+tr[p].r)>>1;
     31     if(tr[p].tag) {
     32         add(p<<1,tr[p].l,mid,tr[p].tag);
     33         add(p<<1|1,mid+1,tr[p].r,tr[p].tag);
     34         tr[p].tag=0;
     35     }
     36     if(r<=mid) add(p<<1,l,r,k);
     37     else if(l>mid) add(p<<1|1,l,r,k);
     38     else add(p<<1,l,mid,k),add(p<<1|1,mid+1,r,k);
     39     up(p);
     40 }
     41 int query(int p,int l,int r) {
     42     if(l==tr[p].l&&r==tr[p].r) return tr[p].val;
     43     int mid=(tr[p].l+tr[p].r)>>1;
     44     if(tr[p].tag) {
     45         add(p<<1,tr[p].l,mid,tr[p].tag);
     46         add(p<<1|1,mid+1,tr[p].r,tr[p].tag);
     47         tr[p].tag=0;
     48     }
     49     if(r<=mid) return query(p<<1,l,r);
     50     else if(l>mid) return query(p<<1|1,l,r);
     51     else return max(query(p<<1,l,mid),query(p<<1|1,mid+1,r));
     52 }
     53 void modify(int p,int x,int k) {
     54     if(tr[p].l==tr[p].r) {
     55         tr[p].val=max(tr[p].val,k);
     56         return;
     57     }
     58     int mid=(tr[p].l+tr[p].r)>>1;
     59     if(tr[p].tag) {
     60         add(p<<1,tr[p].l,mid,tr[p].tag);
     61         add(p<<1|1,mid+1,tr[p].r,tr[p].tag);
     62         tr[p].tag=0;
     63     }
     64     if(x<=mid) modify(p<<1,x,k);
     65     else modify(p<<1|1,x,k);
     66     up(p);
     67 }
     68 inline int R() {
     69     int a=0;char c=getchar();
     70     while(c>'9'||c<'0')c=getchar();
     71     while(c>='0'&&c<='9')a=a*10+c-'0',c=getchar();
     72     return a;
     73 }
     74 int main() {
     75     n=R();
     76     for(int i=1;i<=n;i++) {
     77         A[i]=R(),B[i]=R();
     78         book[++tot]=A[i],book[++tot]=B[i];
     79     }
     80     sort(book+1,book+tot+1);
     81     tot=unique(book+1,book+tot+1)-book-1;
     82     for(int i=1;i<=n;i++) {
     83         A[i]=lower_bound(book+1,book+tot+1,A[i])-book;
     84         B[i]=lower_bound(book+1,book+tot+1,B[i])-book;
     85     }
     86     ++tot;
     87     build(1,1,tot);
     88     for(int i=1;i<=n;i++) {
     89         if(A[i]>B[i]) {
     90             int tmp=query(1,A[i],tot);
     91             add(1,B[i]+1,A[i],1);
     92             modify(1,A[i],tmp+1);
     93         } else {
     94             int tmp=query(1,B[i]+1,tot);
     95             modify(1,A[i],tmp+1);
     96         }
     97     }
     98     printf("%d
    ",tr[1].val);
     99     return 0;
    100 }
    t1 Code


    T2:影魔

      只会离线……

      对于每个节点维护一颗线段树,下标为颜色,权值为该颜色的最浅深度(子树内)

      再对全局开一颗树状数组,下标为深度,权值为种类数

      离线处理询问,最后遍历一边原树

      当进入某节点时,查询该节点所有询问,即子树外对答案的影响

      当即将离开某节点时,再次查询,将本次查询值减去上次查询值即为$answer$

      对于线段树,只需要一层层向上合并即可

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 #include<vector>
     8 using namespace std;
     9 const int MAXN=100233,MAXP=3000233;
    10 int n,m,root[MAXN],clr[MAXN],ans[MAXN];
    11 int ls[MAXP],rs[MAXP],dmi[MAXP],tot;
    12 vector<int> ver[MAXN];
    13 vector<pair<int,int> > que[MAXN];
    14 int dep[MAXN],fa[MAXN];
    15 
    16 int tr[MAXN];
    17 void add(int x,int k) {
    18     for(;x<=n;x+=x&-x) tr[x]+=k;
    19 }
    20 int ask(int x) {
    21     int ret=0;
    22     for(;x;x-=x&-x) ret+=tr[x];
    23     return ret;
    24 }
    25 
    26 void change(int &p,int l,int r,int x,int c) {
    27     if(!p) p=++tot;
    28     if(l==r) {
    29         if(dmi[p]) {
    30             if(dmi[p]>c) add(dmi[p],-1),add(c,1),dmi[p]=c;
    31         } else dmi[p]=c,add(c,1);
    32         return;
    33     }
    34     int mid=(l+r)>>1;
    35     if(x<=mid) change(ls[p],l,mid,x,c);
    36     else change(rs[p],mid+1,r,x,c);
    37 }
    38 void dfs(int u) {
    39     for(int i=0;i<(int)ver[u].size();i++) {
    40         int v=ver[u][i];
    41         dep[v]=dep[u]+1;
    42         dfs(v);
    43     }
    44 }
    45 void merge(int &p1,int p2) {
    46     if(!p1||!p2) return (void)(p1=p1+p2);
    47     if(dmi[p1]||dmi[p2]) {
    48         if(!dmi[p1]||!dmi[p2]) dmi[p1]+=dmi[p2];
    49         else add(max(dmi[p1],dmi[p2]),-1),dmi[p1]=min(dmi[p1],dmi[p2]);
    50         return;
    51     }
    52     merge(ls[p1],ls[p2]);
    53     merge(rs[p1],rs[p2]);
    54 }
    55 void get_ans(int u) {
    56     for(int i=0;i<(int)que[u].size();i++)
    57         ans[que[u][i].second]=-ask(que[u][i].first);
    58     for(int i=0;i<(int)ver[u].size();i++) {
    59         int v=ver[u][i];
    60         get_ans(v);
    61         merge(root[u],root[v]);
    62     }
    63     change(root[u],1,n,clr[u],dep[u]);
    64     for(int i=0;i<(int)que[u].size();i++)
    65         ans[que[u][i].second]+=ask(que[u][i].first);
    66 }
    67 int main() {
    68     scanf("%d%d",&n,&m);
    69     for(int i=1;i<=n;i++) scanf("%d",&clr[i]);
    70     for(int i=2;i<=n;i++) scanf("%d",&fa[i]),ver[fa[i]].push_back(i);
    71     dep[1]=1,dfs(1);
    72     for(int i=1,tu,td;i<=m;i++) {
    73         scanf("%d%d",&tu,&td);
    74         que[tu].push_back(make_pair(min(td+dep[tu],n),i));
    75     }
    76     get_ans(1);
    77     for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    78     return 0;
    79 }
    t2 Code


    T3:抛硬币

      简单dp,刚开始想复杂了(后缀数组???)

      设计状态$f[i][j]$表示用前i个字符,拼出长度为j的不同子序列的个数

      考虑如何转移,$f[i][j]=f[i-1][j-1]+f[i-1][j]-g[string[i]][j]$

             $g[string[i]][j]=f[i-1][j-1]$

      (其中$g[i][j]$表示以字符i结尾,长度为j的子序列个数)

      即:将长度为$j-1$的串后再拼上$string[i]$,或直接取出长度为j的串而不使用$string[i]$

        最后减去本质相同的串的个数

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define ll long long
     7 using namespace std;
     8 const int MAXN=3005;
     9 const ll D=998244353;
    10 int n,L;
    11 ll f[MAXN][MAXN],g[26][MAXN];
    12 char s[MAXN];
    13 int main() {
    14     scanf("%s%d",s+1,&L);
    15     n=strlen(s+1);
    16     for(int i=0;i<=n;i++) f[i][0]=1;
    17     for(int i=1;i<=n;i++) {
    18         for(int j=1;j<=L;j++) {
    19             f[i][j]=(f[i-1][j-1]+f[i-1][j]-g[s[i]-'a'][j])%D;
    20             g[s[i]-'a'][j]=f[i-1][j-1];
    21         }
    22     }
    23     printf("%lld
    ",(f[n][L]%D+D)%D);
    24     return 0;
    25 }
    t3 Code


  • 相关阅读:
    多进程编程
    Python 的下载安装
    cnBlogs windows LIves Writes 安装
    第四章网页文字编排设计
    第三章网页图形图像设计
    第二章网页创意设计思维和方法
    1.3-1.4网页设计的定位和流程
    1.2网页设计的构成要素和特性
    网页编辑常用快捷方式+学习技巧+网站开发流程
    css选择器2——伪类选择器
  • 原文地址:https://www.cnblogs.com/Gkeng/p/11509140.html
Copyright © 2011-2022 走看看