思路:枚举子矩形上下边,再尺取法+单调队列求合法的最长的宽
AC代码:
#include<bits/stdc++.h> typedef long long ll; using namespace std; int n,m,a[505][505]; int q1[505],q2[505]; int maxn[505],minn[505]; int main() { int t;scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&a[i][j]); } } int ans=0; for(int i=1;i<=n;i++){ memset(maxn,0,sizeof(maxn)); memset(minn,0x3f,sizeof(minn)); for(int j=i;j<=n;j++){ int h1=1,t1=0; int h2=1,t2=0; int l=1; for(int k=1;k<=n;k++){ maxn[k]=max(maxn[k],a[j][k]); minn[k]=min(minn[k],a[j][k]); while(h1<=t1&&maxn[q1[t1]]<=maxn[k]) t1--; q1[++t1]=k; while(h2<=t2&&minn[q2[t2]]>=minn[k]) t2--; q2[++t2]=k; while(l<=k&&maxn[q1[h1]]-minn[q2[h2]]>m){ l++; if(q1[h1]<l) h1++; if(q2[h2]<l) h2++; } ans=max(ans,(k-l+1)*(j-i+1)); } } } printf("%d ",ans); } return 0; }
思路:链表模拟增删,Trie树定位字符串的下标
AC代码:
#include<bits/stdc++.h> typedef long long ll; using namespace std; int num=0,st=0,ed=0,sz=0,L[500005*2],R[500005*2],data[500005*2],trie[500005*2]; int tot=1,pos[500005*10],son[500005*10][10]; void init(){ for(int i=1;i<=tot;i++){ for(int j=0;j<10;j++) son[i][j]=0; pos[i]=0; } tot=1; for(int i=0;i<500005*2;i++) L[i]=R[i]=data[i]=trie[i]=0; num=st=ed=sz=0; } void Erase(int id){ int pre=L[id],succ=R[id]; if(pre) R[pre]=succ; if(succ) L[succ]=pre; if(id==st) st=succ; if(id==ed) ed=pre; sz--; } void Insert(int id,int v){ data[id]=v; if(!st) st=ed=id; else R[L[id]=ed]=id,ed=id; sz++; } void InsertTrie(char s[],int id){ int p=1; for(int i=0;s[i];i++){ if(!son[p][s[i]-'0']) son[p][s[i]-'0']=++tot; p=son[p][s[i]-'0']; } pos[p]=id; trie[id]=p; } int SearchTrie(char s[]){ int p=1; for(int i=0;s[i];i++){ p=son[p][s[i]-'0']; if(!p) break; } return pos[p]; } int main() { int t;scanf("%d",&t); while(t--){ init(); int q,m;scanf("%d%d",&q,&m); while(q--){ int op;scanf("%d",&op); char s[10];scanf("%s",s); int v;scanf("%d",&v); int id=SearchTrie(s); if(op==0){ if(id) v=data[id],Erase(id); else if(sz==m) pos[trie[st]]=0,Erase(st); num++; Insert(num,v);InsertTrie(s,num); printf("%d ",v); } else{ if(id==0||(v==-1&&L[id]==0)||(v==1&&R[id]==0)) puts("Invalid"); else{ if(v==-1) id=L[id]; if(v==1) id=R[id]; printf("%d ",data[id]); } } } } return 0; }