2019.2.26

考试过程:

太菜了,不写了

T1

设$dp[i][j]$表示决策到第$i$个格子,此时第$i$个格子的水位线是$j$的最优解。考试的时候一直觉得直接线性DP有后效性,但是我们让低于隔板的部分从隔板下的部分取最大值转移,高于隔板的部分只从等于它的高度转移,就是 区间max+区间修改,用线段树合并优化成$O(n\log 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\n",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\n",pts);
126         for(int i=1;i<=pts;i++)
127             printf("%d %d\n",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\n",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\n",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

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10441338.html
今日推荐