第一题裸四方暴力,一直在想怎么用数据结构优化,期间想到了主席树套二维线段树,然而会爆空间,但是只要从上到下从左到右便可以只要主席树了,然后动态开点就是
O(n2logn)
的空间,还是对主席树不熟练啊,我毕竟是以前只写过一次的蒟蒻。
第二题AC自动机搞啊,裸裸的,然而我写了个
O(n2)
居然只超了两个点,考场上,下考后都自以为是
O(n)
。我果然是无脑工业狗,一看见就开始怒敲AC自动机。
第三题考虑陈丹琪分治,接下来便考虑如何快速求出一条直线是否切割了凸包。对于一个直线方程
Ax+By+C=0
和点
(x,y)
,如果把点代入方程大于0则在直线上方,小于0反之。问题便转化为了凸包上这些点的最大值和最小值是否同号。
由于上下凸壳的函数值均为单峰函数,考虑三分即可。
此题我调了TM好久,三个错误:
一、以为上凸壳的函数就是上凸的,下凸壳的函数就是下凸的,导致三分挂掉;
二、判断同号时直接相乘判断正负,爆LL;
三、三分的复杂度是以1.5为底的,一个for循环for20遍少了。
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define zqf 1000000007
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const int MAXN=751*751;
int n,m,k,T[MAXN],st[10000001],top=0,q,v,cnt;
int dp[751][751],sum[750],w[751][751],lc[10000001],rc[10000001],Sum[10000001];
void Read(int& x)
{
x=0;char c;int flag=0;
while(c=getchar())
{
if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
}
void insert(int& root,int l,int r)
{
cnt++;
if(!root)
root=st[--top];
if(l==r)
{
Sum[root]=(Sum[root]+v)%zqf;
return;
}
int mid=(l+r)>>1;
if(q<=mid)
insert(lc[root],l,mid);
else
insert(rc[root],mid+1,r);
Sum[root]=(Sum[lc[root]]+Sum[rc[root]])%zqf;
}
int query(int now,int l,int r)
{
cnt++;
if(!now)return 0;
if(l>=1&&r<=q)
{
return Sum[now];
}
int mid=(l+r)>>1,a=0;
if(1<=mid)
a=(a+query(lc[now],l,mid))%zqf;
if(q>mid)
a=(a+query(rc[now],mid+1,r))%zqf;
return a;
}
int main()
{
freopen("hopscotch.in","r",stdin);
freopen("hopscotch.out","w",stdout);
for(int i=0;i<7000000;i++)st[++top]=i+1;
Read(n);Read(m);Read(k);
dp[1][1]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
Read(w[i][j]);
for(int i=2;i<=n;i++)
{
int SUM=0;
for(int j=2;j<=m;j++)
{
if(i==3&&j==4)
i=3;
sum[j-1]=(sum[j-1]+dp[i-1][j-1])%zqf;
SUM=(sum[j-1]+SUM)%zqf;
q=j-1;v=dp[i-1][j-1];cnt=0;
insert(T[w[i-1][j-1]],1,m);
cnt=0;
dp[i][j]=(SUM-query(T[w[i][j]],1,m))%zqf;
if(dp[i][j]<0)dp[i][j]=(dp[i][j]+zqf)%zqf;
}
}
printf("%d\n",dp[n][m]);
}
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const int MAXN=2e5;
int n,match[MAXN],flag=0,next[MAXN],from[MAXN],jg=0,M,st[MAXN],top;
char s[MAXN],tmp[MAXN];
struct ACM{
int son[MAXN][27],f[MAXN],last[MAXN],val[MAXN],tot,Len[MAXN];
ACM(){
memset(son,0,sizeof(son));
memset(f,0,sizeof(f));
memset(last,0,sizeof(last));
memset(val,0,sizeof(val));
tot=0;
}
int idx(char c)
{
return c-'a';
}
void insert(char* S)
{
int m=strlen(S+1),u=0;
for(int i=next[0];i<=m;i=next[i])
{
int v=idx(S[i]);
if(!son[u][v])
son[u][v]=++tot;
u=son[u][v];
}
val[u]=1;
Len[u]=m;
}
void getFail()
{
queue<int> q;
for(int i=0;i<26;i++)
{
if(son[0][i])
{
q.push(son[0][i]);
f[son[0][i]]=last[son[0][i]]=0;
}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int i=0;i<26;i++)
{
int u=son[r][i];
if(!u){son[r][i]=son[f[r]][i];continue;}
q.push(u);
int j=f[r];
while(j&&!son[j][i])j=f[j];
f[u]=son[j][i];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
void update(int& now,int l,int& p)
{
int cnt=1,o=now,fuck=0;
while(1)
{
++fuck;
//DEBUG("%d\n",fuck);
if(cnt==l)
{
match[now]=o;
match[o]=now;
break;
}
now=from[now];
cnt++;
p=st[--top];
}
next[from[now]]=next[o];
from[next[o]]=from[now];
now=from[now];
p=st[--top];
}
void find(char* S)
{
++jg;
//if(jg%10000==0)DEBUG("%d\n",jg);
int j=0,cnt=0;
top=0;
st[++top]=j;
for(int i=next[0];i<=M;i=next[i])
{
++cnt;
//DEBUG("%d\n",cnt);
int v=idx(S[i]);
j=son[j][v];
st[++top]=j;
if(val[j])
{
flag=1;
update(i,Len[j],j);
}
}
}
}Ac;
int main()
{
freopen("censor.in","r",stdin);
freopen("censor.out","w",stdout);
memset(match,-1,sizeof(match));
scanf("%s",s+1);
M=strlen(s+1);
for(int i=0;i<MAXN;i++)next[i]=i+1,from[i]=i-1;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",tmp+1);
Ac.insert(tmp);
}
Ac.getFail();
while(1)
{
Ac.find(s);
if(!flag)break;
flag=0;
}
for(int i=next[0];i<=M;i=next[i])
putchar(s[i]);
puts("");
}
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<climits>
#define X first
#define Y second
#define DB double
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define int LL
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const int MAXN=3e5;
struct op{
int t,a,b,c;
op(int t=0,int a=0,int b=0,int c=0):t(t),a(a),b(b),c(c){}
}oper[MAXN];
template<typename T> void Read(T& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
int n,ans[MAXN],tot=0,p,q;
bool cant[MAXN];
pii pot[MAXN],ch[MAXN];
int cross(const pii& a,const pii& b)
{
return a.X*b.Y-a.Y*b.X;
}
pdd operator -(const pii& a,const pii& b)
{
return MP(a.X-b.X,a.Y-b.Y);
}
void CovHull(int l,int r)
{
p=q=0;
sort(pot,pot+tot);
for(int i=0;i<tot;i++){
while(p>1&&cross(ch[p-1]-ch[p-2],pot[i]-ch[p-2])<=0)p--;
ch[p++]=pot[i];
}
q=p;
for(int i=tot-2;i>=0;i--){
while(p>q&&cross(ch[p-1]-ch[p-2],pot[i]-ch[p-2])<=0)p--;
ch[p++]=pot[i];
}
p--;
}
int sgn(int x)
{
return x<0?-1:1;
}
int F(int id,pii P)
{
return oper[id].a*P.X+oper[id].b*P.Y+oper[id].c;
}
int UPgetmax(int id,int ql,int qr)
{
int l=ql,r=qr;
if(qr<ql)return -INF;
for(int i=1;i<=25;i++)
{
int m1=l+(r-l+1)/3,
m2=r-(r-l+1)/3;
if(F(id,ch[m1])>F(id,ch[m2]))
r=m2;
else
l=m1;
}
return max(F(id,ch[r]),F(id,ch[l]));
}
int Cgetmax(int id,int ql,int qr)
{
if(ql>qr)
return -INF;
int l=ql,r=qr;
return max(F(id,ch[r]),F(id,ch[l]));
}
int DOWNgetmin(int id,int ql,int qr)
{
int l=ql,r=qr;
if(qr<ql)return INF;
for(int i=1;i<=25;i++)
{
int m1=l+(r-l+1)/3,
m2=r-(r-l+1)/3;
if(F(id,ch[m1])<F(id,ch[m2]))
r=m2;
else
l=m1;
}
return min(F(id,ch[r]),F(id,ch[l]));
}
int Cgetmin(int id,int ql,int qr)
{
if(ql>qr)return INF;
return min(F(id,ch[ql]),F(id,ch[qr]));
}
void _cdq_Div_Con(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1;
tot=0;
for(int i=l;i<=mid;i++)
if(oper[i].t==1)
pot[tot++]=MP(oper[i].a,oper[i].b);
CovHull(l,r);
if(tot==0)
{
_cdq_Div_Con(mid+1,r);
return;
}
for(int i=mid+1;i<=r;i++)
if(oper[i].t==2&&!cant[i])
{
int mx=max(max(UPgetmax(i,0,q-1),Cgetmax(i,0,q-1)),max(UPgetmax(i,q,p-1),Cgetmax(i,q,p-1))),
mn=min(min(Cgetmin(i,0,q-1),DOWNgetmin(i,0,q-1)),min(DOWNgetmin(i,q,p-1),Cgetmin(i,q,p-1)));
if(ans[i]!=0)
if(mx==0||mx==0||sgn(mx)!=sgn(mn)||sgn(mx)!=sgn(ans[i]))
cant[i]=1;
if(mx==0||mn==0||sgn(mx)*sgn(mn)<0)cant[i]=1;
ans[i]=sgn(mx);
}
_cdq_Div_Con(l,mid);
_cdq_Div_Con(mid+1,r);
}
main()
{
#ifndef ONLINE_JUDGE
freopen("fencing.in","r",stdin);
freopen("fencing.out","w",stdout);
#endif
Read(n);Read(q);
for(int i=1;i<=n;i++)
{
int a,b;
Read(a);Read(b);
oper[i]=op(1,a,b,0);
}
for(int i=1;i<=q;i++)
{
int a,b,c,d;
Read(a);
if(a==1)
{
Read(b);Read(c);
oper[n+i]=op(a,b,c,0);
}
else
{
Read(b);Read(c);Read(d);
oper[n+i]=op(a,b,c,-d);
}
}
n+=q;
_cdq_Div_Con(1,n);
for(int i=1;i<=n;i++)
if(oper[i].t==2)
{
if(!cant[i])
puts("YES");
else
puts("NO");
}
}