少一句话,AK失败
不过跟熊god并列rank1也是一件幸事
T1 q次询问一个字符串两个后缀的最长前缀
10分钟打了一个后缀数组RMQ
然后过了样例 跟对拍拍过了1e7组数据
就没管它
考完试之后发现有$l==r$的情况。。。
于是爆炸 炸到30分
加一句话就100分 就整场比赛ak
淦
当然 如果你不会后缀数组
我们可以hash
每次二分一个长度,O(1)判断哈希值是否相等
#include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int maxn = 2e5 + 10; char str[maxn];int n; int st[maxn],top,lb[maxn],rb[maxn],r[maxn]; namespace Suffix_Array { int rnk[maxn],tmp[maxn],sa[maxn],hei[maxn]; int stb[maxn][20]; int k; inline bool cmp(int i,int j) { if(rnk[i]!=rnk[j]) return rnk[i]<rnk[j]; else { int ri=i+k<=n? rnk[i+k]:-1; int rj=j+k<=n? rnk[j+k]:-1; return ri<rj; } } void GetSA() { for(int i=0;i<=n;i++) { sa[i]=i; rnk[i]=i<n?str[i]:-1; } for(k=1;k<=n;k<<=1) { sort(sa,sa+n+1,cmp); tmp[sa[0]]=0; for(int i=1;i<=n;i++)tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0); for(int i=0;i<=n;i++)rnk[i]=tmp[i]; } } void GetHeight() { for(int i=0;i<=n;i++)rnk[sa[i]]=i; int h=0;hei[0]=0; for(int i=0;i<n;i++) { if(h!=0)h--; if(!rnk[i])continue; int t=sa[rnk[i]-1]; for(;i+h<n && t+h<n;h++) if(str[i+h]!=str[t+h]) break; hei[rnk[i]]=h; } } void initMin() { for(int i=1;i<=n;i++) stb[i][0] = hei[i]; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) stb[i][j] = min(stb[i][j-1],stb[i+(1<<(j-1))][j-1]); } int RMQ(int L,int R) { int k=0; while((1<<(k+1)) <= R-L+1)k++; return min(stb[L][k],stb[R-(1<<k)+1][k]); } int LCP(int i,int j) { int L=rnk[i],R=rnk[j]; if(L>R)swap(L,R); L++;return RMQ(L,R); } } using namespace Suffix_Array; int main() { freopen("lcp10.in","r",stdin); freopen("lcp10.out","w",stdout); scanf("%s",str); n = strlen(str); GetSA();GetHeight();initMin(); int q = read(); int ans = 0; while(q--) { int l = read(),r = read(); if(l==r){cout<<n - l + 1<<endl;continue;}//一开始没写这句话 wa了 cout<<LCP(l - 1,r - 1)<<endl; } }
T2 询问两个线段有没有交点
板子
#include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int maxn = 1e5 + 10; struct Vector { double x,y; Vector operator + (const Vector &b)const { return (Vector){x + b.x,y + b.y}; } Vector operator - (const Vector &b)const { return (Vector){x - b.x,y - b.y}; } double operator * (const Vector &b)const { return x * b.x + y * b.y; } double len(){return (*this) * (*this);} double operator ^ (const Vector &b)const { return x * b.y - y * b.x; } void readvec() { x = read() * 1.0; y = read() * 1.0; } }; #define Point Vector struct Segment { Point st,ed; }ps[maxn << 1]; double dis(Point a,Point b){return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));} double Area(Vector a,Vector b,Vector c){return (b - a) ^ (c - a);} bool Intersec(Point a,Point b,Point c,Point d) { if(max(a.x,b.x)<min(c.x,d.x))return false; if(max(a.y,b.y)<min(c.y,d.y))return false; if(max(c.x,d.x)<min(a.x,b.x))return false; if(max(c.y,d.y)<min(a.y,b.y))return false; if(Area(c,b,a)*Area(b,d,a)<0)return false; if(Area(a,d,c)*Area(d,b,c)<0)return false; return true; } int main() { freopen("intersect.in","r",stdin); freopen("intersect.out","w",stdout); int T = read(); while(T--) { int n = read(); ps[0].st.readvec();ps[0].ed.readvec(); for(int i=1;i<=n;i++) { ps[i].st.readvec(); ps[i].ed.readvec(); } int flag = 0; for(int i=1;i<=n;i++) { if(Intersec(ps[0].st,ps[0].ed,ps[i].st,ps[i].ed)) { flag = 1;break; } } if(flag)puts("YES"); else puts("NO"); } }
T3 图论
你在点1处可以带一些油,每条道路有一个额外的权值c,表示当你剩余至少c的油的时候才能走这条路,走路需要费油
求1到n至少要带多少油
二分dij
结论...不是很会证明
二分一个油量,暴力从1到n沿当前能走的最短路走,判断能不能走到n就可以了
#include<bits/stdc++.h> #define maxn 100005 #define LL long long using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } struct pa { int x;LL dis; bool operator <(const pa t1) const {return dis>t1.dis;} }; bool vis[maxn]; priority_queue<pa> q; int first[maxn],to[maxn << 1],nx[maxn << 1],v1[maxn << 1],v2[maxn << 1],cnt; void add(int u,int v,LL c,LL w){to[++cnt] = v;nx[cnt] = first[u];first[u] = cnt;v1[cnt] = c;v2[cnt] = w;} int n,m; LL dis[maxn]; bool flag=0; bool check(LL mid) { memset(vis,0,sizeof(vis)); for(int i=2;i<=n;i++) dis[i]=1e9 + 777;dis[1]=0; q.push((pa){1,0}); while(!q.empty()) { pa now=q.top();q.pop(); if(vis[now.x]) continue; vis[now.x]=1; for(int i=first[now.x];i;i=nx[i]) { if(mid-now.dis<v2[i]) continue; if(dis[to[i]]>now.dis+v1[i]) { dis[to[i]]=now.dis+v1[i]; q.push((pa){to[i],dis[to[i]]}); } } } if(vis[n]) flag=1; return vis[n]; } int main() { freopen("spaceship.in","r",stdin); freopen("spaceship.out","w",stdout); n=read(),m=read(); for(int i=1;i<=m;i++) { int u=read(),v=read(),c=read(),w=read(); add(u,v,c,w);add(v,u,c,w); } LL l=0,r=2147483233333333LL; LL ans = 0; while(l<=r) { LL mid=(l+r)>>1; if(check(mid)) {r=mid-1;ans = mid;} else l=mid+1; } if(flag==0) printf("-1 "); else printf("%lld ",ans); }