• 2019.2.26 考试


    T1

    设$dp[i][j]$表示决策到第$i$个格子,此时第$i$个格子的水位线是$j$的最优解。考试的时候一直觉得直接线性DP有后效性,但是我们让低于隔板的部分从隔板下的部分取最大值转移,高于隔板的部分只从等于它的高度转移,就是 区间max+区间修改,用线段树合并优化成$O(nlog h)$

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int N=100005,M=1.2e7+70,Maxx=1e6,inf=1e9;
      6 int h[N],root[N],son[M][2],mxx[M],laz[M];
      7 int T,n,m,z,t1,t2,t3,tot;
      8 void i207M()
      9 {
     10     for(int i=1;i<=tot;i++) 
     11         son[i][0]=son[i][1]=mxx[i]=laz[i]=0;
     12     for(int i=1;i<=n;i++) root[i]=0; tot=0;
     13 }
     14 void Pushup(int nde)
     15 {
     16     int ls=son[nde][0],rs=son[nde][1];
     17     mxx[nde]=max(ls?mxx[ls]:-inf,rs?mxx[rs]:-inf);
     18 }
     19 void Release(int nde)
     20 {
     21     int &ls=son[nde][0],&rs=son[nde][1];
     22     if(!ls) ls=++tot; if(!rs) rs=++tot;
     23     if(laz[nde])
     24     {
     25         int &lz=laz[nde];
     26         laz[ls]+=lz,laz[rs]+=lz;
     27         mxx[ls]+=lz,mxx[rs]+=lz,lz=0;
     28     }
     29 }
     30 void Change(int &nde,int l,int r,int ll,int rr,int tsk)
     31 {
     32     if(l>rr||r<ll)
     33         return ;
     34     else
     35     {
     36         if(!nde) nde=++tot;
     37         if(l>=ll&&r<=rr)
     38             mxx[nde]+=tsk,laz[nde]+=tsk;
     39         else
     40         {
     41             int mid=(l+r)>>1; Release(nde);
     42             Change(son[nde][0],l,mid,ll,rr,tsk);
     43             Change(son[nde][1],mid+1,r,ll,rr,tsk);
     44             Pushup(nde);
     45         }
     46     }
     47 }
     48 int Query(int &nde,int l,int r,int ll,int rr)
     49 {
     50     if(l>rr||r<ll)
     51         return -inf;
     52     else
     53     {
     54         if(!nde) return 0;
     55         if(l>=ll&&r<=rr)
     56         {
     57             int ret=mxx[nde];
     58             nde=0; return ret;
     59         }
     60         else
     61         {
     62             int mid=(l+r)>>1; Release(nde);
     63             return max(Query(son[nde][0],l,mid,ll,rr),
     64                        Query(son[nde][1],mid+1,r,ll,rr));
     65         }
     66     }
     67 }
     68 int Merge(int x,int y)
     69 {
     70     if(!x||!y) return x+y;
     71     if(!son[x][0]&&!son[x][1]) swap(x,y);
     72     if(!son[y][0]&&!son[y][1])
     73         mxx[x]+=laz[y],laz[x]+=laz[y];
     74     else
     75     {
     76         Release(x),Release(y);
     77         son[x][0]=Merge(son[x][0],son[y][0]);
     78         son[x][1]=Merge(son[x][1],son[y][1]);
     79         Pushup(x);
     80     }
     81     return x;
     82 }
     83 int main()
     84 {
     85     scanf("%d",&T);
     86     while(T--)
     87     {
     88         scanf("%d%d",&n,&m),i207M();
     89         for(int i=2;i<=n;i++)
     90             scanf("%d",&h[i]);
     91         for(int i=1;i<=m;i++)
     92         {
     93             scanf("%d%d%d",&t1,&t2,&t3),t2++;
     94             if(t3) Change(root[t1],0,Maxx,t2,Maxx,1); 
     95             else Change(root[t1],0,Maxx,0,t2-1,1);
     96         }
     97         for(int i=2;i<=n;i++)
     98         {
     99             int pm=Query(root[i-1],0,Maxx,0,h[i]);
    100             Change(root[i],0,Maxx,0,h[i],pm);
    101             root[i]=Merge(root[i-1],root[i]);
    102         }//for(int i=1;i<=n;i++)
    103         printf("%d
    ",Query(root[n],0,Maxx,0,Maxx));
    104     }
    105     return 0;
    106 }
    View Code

    T2 

    讲烂了的结论题.jpg

    从一个未匹配点沿着未匹配-匹配边不断走,路上的点都是不一定在最大匹配里的

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int N=105,M=20005,E=100005,inf=1e9;
      6 const int mov[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
      7 int T,n,m,s,t,f,b,pts,ava,cnt,tot,maxx;
      8 int p[M],pp[M],noww[E],goal[E],flow[E];
      9 int mapp[N][N],idx[N][N],dep[M],que[M],mat[M],ntp[M];
     10 char str[N];
     11 struct a
     12 {
     13     int x,y;
     14 }ans[N];
     15 bool cmp(a xx,a yy)
     16 {
     17     return xx.x==yy.x?xx.y<yy.y:xx.x<yy.x;
     18 }
     19 bool Check(int x,int y)
     20 {
     21     return x>=1&&x<=n&&y>=1&&y<=m&&mapp[x][y];
     22 }
     23 void Link(int f,int t,int v)
     24 {
     25     noww[++cnt]=p[f],p[f]=cnt;
     26     goal[cnt]=t,flow[cnt]=v;
     27     noww[++cnt]=p[t],p[t]=cnt;
     28     goal[cnt]=f,flow[cnt]=0;
     29 }
     30 void Init(int st,int ed)
     31 {
     32     for(int i=1;i<=ed;i++)
     33         pp[i]=p[i],dep[i]=-1;
     34     dep[st]=0,que[f=b=0]=st;
     35 }
     36 bool Layering(int st,int ed)
     37 {
     38     Init(st,ed);
     39     while(f<=b)
     40     {
     41         int tn=que[f++];
     42         for(int i=pp[tn];i;i=noww[i])
     43             if(flow[i]&&dep[goal[i]]==-1)
     44                 dep[goal[i]]=dep[tn]+1,que[++b]=goal[i];
     45     }
     46     return ~dep[ed];
     47 }
     48 int Augmenting(int nd,int ed,int mn)
     49 {
     50     if(nd==ed||!mn) return mn;
     51     int tmp,tep=0;
     52     for(int i=pp[nd];i;i=noww[i])
     53     {
     54         pp[nd]=i;
     55         if(dep[goal[i]]==dep[nd]+1)
     56             if(tmp=Augmenting(goal[i],ed,min(mn,flow[i])))
     57             {
     58                 flow[i]-=tmp,mn-=tmp;
     59                 flow[i^1]+=tmp,tep+=tmp; 
     60                 if(!mn) break;
     61             }
     62     }
     63     return tep;
     64 }
     65 int Dinic_Maxflow()
     66 {
     67     int ret=0;
     68     while(Layering(s,t)) 
     69         ret+=Augmenting(s,t,inf);
     70     return ret;
     71 }
     72 void Match(int nde)
     73 {
     74     for(int i=p[nde];i;i=noww[i])
     75         if(!flow[i]&&goal[i]!=s)
     76             mat[goal[i]]=nde,mat[nde]=goal[i];
     77 }
     78 void Getans(int nde)
     79 {
     80     ntp[nde]=true;
     81     for(int i=p[nde];i;i=noww[i])
     82         if(!ntp[mat[goal[i]]])
     83             Getans(mat[goal[i]]);
     84 }
     85 int main()
     86 {
     87     scanf("%d%d",&n,&m);
     88     for(int i=1;i<=n;i++)
     89     {
     90         scanf("%s",str+1);
     91         for(int j=1;j<=m;j++)
     92             mapp[i][j]=str[j]=='.',idx[i][j]=++tot;
     93     }
     94     s=tot+1,t=s+1,cnt=1;
     95     for(int i=1;i<=n;i++)
     96         for(int j=1;j<=m;j++)
     97             if(mapp[i][j])
     98             {
     99                 if((i+j)%2) Link(idx[i][j],t,1);
    100                 else 
    101                 {
    102                     Link(s,idx[i][j],1);
    103                     for(int k=0,t1,t2;k<4;k++)
    104                         if(Check(t1=i+mov[k][0],t2=j+mov[k][1]))
    105                             Link(idx[i][j],idx[t1][t2],1);
    106                 }
    107                 ava+=mapp[i][j];
    108             }
    109     maxx=Dinic_Maxflow(); 
    110     if(maxx==ava/2&&ava%2==0) printf("0");
    111     else
    112     {
    113         for(int i=1;i<=n;i++)
    114             for(int j=1;j<=m;j++) 
    115                 if(mapp[i][j]&&(i+j)%2==0) Match(idx[i][j]);
    116         //for(int i=1;i<=n*m;i++) printf("%d ",mat[i]);
    117         for(int i=1;i<=n;i++)
    118             for(int j=1;j<=m;j++)
    119                 if(mapp[i][j]&&!mat[idx[i][j]]) Getans(idx[i][j]);
    120         for(int i=1;i<=n;i++)
    121             for(int j=1;j<=m;j++)
    122                 if(ntp[idx[i][j]]) 
    123                     pts++,ans[pts].x=i,ans[pts].y=j;
    124         sort(ans+1,ans+1+pts,cmp);
    125         printf("%d
    ",pts);
    126         for(int i=1;i<=pts;i++)
    127             printf("%d %d
    ",ans[i].x,ans[i].y);
    128     }
    129     return 0;
    130 }
    View Code

    T3

    发现题目实际上不是$k,q<=100000$,是$k*q=sum w<=100000$

    分块。对于$k>sqrt m$先在SAM上暴力把串跑一次,记录下每个位置最后的节点在哪,然后变成求每个询问的子串出现次数;对于$k<sqrt m$直接$k^2$枚举所有子串来做。

      1 #include<cstdio>
      2 #include<vector>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define vint vector<int>
      6 #define vit vector<int>::iterator 
      7 using namespace std;
      8 const int N=200005,Sq=320,K=20;
      9 int n,m,q,k,t1,t2,cnt,lst,tot; 
     10 int p[N],noww[N],goal[N],ll[N],rr[N]; 
     11 int trs[N][26],fth[N],siz[N],len[N],anc[N][K]; 
     12 char str[N],rd[N]; int qlen[N],qpos[N];
     13 vint sub[Sq][Sq];
     14 void Link(int f,int t)
     15 {
     16     noww[++cnt]=p[f];
     17     goal[cnt]=t,p[f]=cnt;
     18 }
     19 void Insert(int ch)
     20 {
     21     int nde=lst,newn=++tot; lst=newn;
     22     siz[newn]=1,len[newn]=len[nde]+1;
     23     while(nde&&!trs[nde][ch])
     24         trs[nde][ch]=newn,nde=fth[nde];
     25     if(!nde) fth[newn]=1;
     26     else 
     27     {
     28         int tran=trs[nde][ch];
     29         if(len[tran]==len[nde]+1)
     30             fth[newn]=tran;
     31         else 
     32         {
     33             int rnde=++tot; len[rnde]=len[nde]+1;
     34             for(int i=0;i<=25;i++) trs[rnde][i]=trs[tran][i];
     35             fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde;
     36             while(nde&&trs[nde][ch]==tran)
     37                 trs[nde][ch]=rnde,nde=fth[nde];
     38         }
     39     }
     40 }
     41 void DFS(int nde)
     42 {
     43     anc[nde][0]=fth[nde];
     44     for(int i=1;i<=19;i++)
     45         anc[nde][i]=anc[anc[nde][i-1]][i-1];
     46     for(int i=p[nde];i;i=noww[i])
     47         DFS(goal[i]),siz[nde]+=siz[goal[i]];
     48 }
     49 void Pre()
     50 {
     51     lst=tot=1;
     52     for(int i=0;i<n;i++) Insert(str[i]-'a');
     53     for(int i=1;i<=tot;i++) Link(fth[i],i); DFS(1);
     54 } 
     55 int Query(vint ve,int ll,int rr)
     56 {
     57     vit it1=lower_bound(ve.begin(),ve.end(),ll);
     58     vit it2=upper_bound(ve.begin(),ve.end(),rr);
     59     return it2-it1;
     60 }
     61 void Solve1()
     62 {
     63     while(q--)
     64     {
     65         long long ans=0;
     66         scanf("%s%d%d",rd,&t1,&t2);
     67         for(int i=0;i<k;i++)
     68         {
     69             int nde=1;
     70             for(int j=i;j<k;j++)
     71             {
     72                 int ch=rd[j]-'a';
     73                 if(!trs[nde][ch]) break;
     74                 nde=trs[nde][ch];
     75                 ans+=1ll*siz[nde]*Query(sub[i][j],t1,t2);
     76             }
     77         }
     78         printf("%lld
    ",ans);
     79     }
     80 }
     81 int Climb(int lth,int nde)
     82 {
     83     for(int i=19;~i;i--)
     84         if(lth<=len[anc[nde][i]])
     85             nde=anc[nde][i];
     86     return siz[nde];
     87 }
     88 void Solve2()
     89 {
     90     while(q--)
     91     {
     92         int nde=1; long long ans=0;
     93         scanf("%s%d%d",rd,&t1,&t2);
     94         for(int i=0,lth=0;i<k;i++)
     95         {
     96             int ch=rd[i]-'a';
     97             while(nde&&!trs[nde][ch])
     98                 nde=fth[nde],lth=len[nde]; 
     99             if(!nde) nde=1,qlen[i]=0;
    100             else nde=trs[nde][ch],qlen[i]=++lth;
    101             qpos[i]=nde;
    102         }
    103         for(int i=t1;i<=t2;i++)
    104             if(qlen[rr[i]]>=rr[i]-ll[i]+1)
    105                 ans+=Climb(rr[i]-ll[i]+1,qpos[rr[i]]);
    106         printf("%lld
    ",ans);
    107     }
    108 }
    109 int main()
    110 {
    111     scanf("%d%d%d%d%s",&n,&m,&q,&k,str);
    112     for(int i=0;i<m;i++)         
    113     {
    114         scanf("%d%d",&ll[i],&rr[i]);
    115         if(k<=Sq) sub[ll[i]][rr[i]].push_back(i);
    116     }
    117     Pre(),k<=Sq?Solve1():Solve2();
    118     return 0;
    119 }
    View Code
  • 相关阅读:
    [LeetCode]Contains Duplicate
    C++基础之泛型算法
    KMP算法
    [LeetCode]Shortest Palindrome
    [LeetCode]House Robber
    Palindrome Linked List leetcode
    Rotate Array leetcode
    Rotate Image LeetCode
    Rotate List leetcode
    Reorder List leetcode
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10441338.html
Copyright © 2020-2023  润新知