线段树可卡时限过 (1500MS)

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int M=1e5+5; int a[M],b[M],mpa[M],mpb[M]; int treea[M<<2],treeb[M<<2]; void up(int root){ treea[root]=min(treea[root<<1],treea[root<<1|1]); treeb[root]=min(treeb[root<<1],treeb[root<<1|1]); } void build(int root,int l,int r){ if(l==r){ treea[root]=a[l]; treeb[root]=b[l]; return ; } int midd=(l+r)>>1; build(root<<1,l,midd); build(root<<1|1,midd+1,r); up(root); } int querya(int L,int R,int root,int l,int r){ if(L<=l&&r<=R){ return treea[root]; } int midd=(l+r)>>1; int ans=inf; if(L<=midd) ans=min(ans,querya(L,R,root<<1,l,midd)); if(R>midd) ans=min(ans,querya(L,R,root<<1|1,midd+1,r)); return ans; } int queryb(int L,int R,int root,int l,int r){ if(L<=l&&r<=R){ return treeb[root]; } int midd=(l+r)>>1; int ans=inf; if(L<=midd) ans=min(ans,queryb(L,R,root<<1,l,midd)); if(R>midd) ans=min(ans,queryb(L,R,root<<1|1,midd+1,r)); return ans; } int main(){ int n; while(scanf("%d",&n)!=EOF){ memset(treea,0x3f,sizeof(treea)); memset(treeb,0x3f,sizeof(treeb)); for(int i=1;i<=n;i++) scanf("%d",&a[i]),mpa[a[i]]=i; for(int i=1;i<=n;i++) scanf("%d",&b[i]),mpb[b[i]]=i; build(1,1,n); int now=1,i; int flag=1; for( i=1;i<=n;i++){ for(int j=1;j<=i;){ int x=querya(j,i,1,1,n); int y=queryb(j,i,1,1,n); // cout<<i<<"!!!!!"<<j<<endl; if(mpa[x]==mpb[y]) j=mpa[x]+1; else{ flag=0; break; } } if(!flag) break; } printf("%d ",i-1); } return 0; }
单调队列做法(160MS)

#include<bits/stdc++.h> using namespace std; vector<int>aa,bb; const int M=1e5+5; int a[M],b[M]; int main(){ int n; while(~scanf("%d",&n)){ aa.clear(); bb.clear(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); int i; for(i=1;i<=n;i++){ while(!aa.empty()&&aa.back()>a[i]) aa.pop_back(); while(!bb.empty()&&bb.back()>b[i]) bb.pop_back(); aa.push_back(a[i]); bb.push_back(b[i]); if(aa.size()!=bb.size()) break; } printf("%d ",i-1); //cout<<"!!"<<endl; } return 0; }
参考博客:https://www.cnblogs.com/Dillonh/p/11209476.html
小队的人推到第3项是正确的,有兴趣的小伙伴可以尝试推推第4项

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int M=1e3+3; const int mod=1e9+7; ll a[M]; ll ni(ll x,ll y=mod-2){ ll t=1; while(y){ if(y&1) t=t*x%mod; x=x*x%mod; y>>=1; } return t; } int main(){ int n; while(~scanf("%d",&n)){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); ll ans=0; for(int i=1;i<=n;i++){ ll t=1ll; for(int j=1;j<=n;j++){ if(i==j) continue; t=(t*((a[j]*a[j]-a[i]*a[i])%mod+mod)%mod)%mod; } t=(t*2*a[i]%mod)%mod; ans=(ans+ni(t))%mod; } printf("%lld ",ans); } }
题意:就是要你构造出一个含‘A’和‘B’的序列,然后要求可以分成n个AB和m个BA(其中一旦某个字符被拿去构成AB或BA那么下次就不能再用他来构造了)
分析:我们先考虑当前序列只有n个A可拿来进行构造,没有B,那么在下一位中是不是只能是B?答案是肯定的,因为,你只能构成AB或BA的俩种,而后者已经明确不能构成(因为前面没有B可拿来构造),那么只能是AB这种顺序的。也就是说当i(我们认为可以是可用来构造序列的A的个数)-j(我们认为可以是可用来构造序列的A的个数)<n的话,我们可以加A,即那么下一个[i+1][j]的方案数一定包含当前的方案数也就是直接加上[i][j],即使用dp来完成这个步骤。加B的操作也是类似

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int M=2e3+2; const ll mod=1e9+7; ll dp[M][M]; int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ int len=n+m; for(int i=0;i<=len;i++) for(int j=0;j<=len;j++) dp[i][j]=0; dp[0][0]=1; for(int i=0;i<=len;i++) for(int j=0;j<=len;j++){ if(i-j<n) dp[i+1][j]=(dp[i+1][j]+dp[i][j])%mod; if(j-i<m) dp[i][j+1]=(dp[i][j+1]+dp[i][j])%mod; } printf("%d ",dp[len][len]); } return 0; }
理解粗:https://blog.csdn.net/monochrome00/article/details/98205456

#include<bits/stdc++.h> using namespace std; const int M=5e3+3; int head[M],match[M],a[M],book[M],col[M],vis[M]; int n,tot; struct node{ int v,nextt; }e[M*M]; void addedge(int u,int v){ e[tot].v=v; e[tot].nextt=head[u]; head[u]=tot++; } bool check(int x){ for(int i=0;i<=30;i++){ if((1<<i)==x) return true; } return false; } bool dfs(int x){ book[x]=1; for(int i=head[x];~i;i=e[i].nextt){ int v=e[i].v; if(!book[v]){ book[v]=1; if(!match[v]||dfs(match[v])){ match[v]=x; match[x]=v; return true; } } } return false; } int main(){ memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); int x=a[i],countt=0; while(x){ countt+=x&1; x>>=1; } col[i]=countt&1; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ { //cout<<"@@"<<(a[i]^a[j])<<endl; if(check(a[i]^a[j])){ if(col[i]==0) addedge(i,j); else addedge(j,i); } } } int ans=0; for(int i=1;i<=n;i++) if(col[i]==0){ for(int j=1;j<=n;j++) book[j]=0; if(dfs(i)) ans++; } printf("%d ",n-ans); for(int j=1;j<=n;j++) book[j]=0; for(int i=1;i<=n;i++){ // cout<<match[i]<<endl; if(col[i]==0&&!match[i]) dfs(i); } for(int i=1;i<=n;i++){ if((col[i]==0&&book[i])||(col[i]==1&&!book[i])) printf("%d ",a[i]); } return 0; }
题意:给定n(我们要构造除的字符串长度)m(m*(m-1)/2组条件)每个条件的意思是:删除构造字符串中除了c1,c2以外的字符剩下来的字符串
由于是有先后顺序的,所以考虑用拓扑排序来接,因为拓扑排序是以入度为0开始算,我们把这个入度为0在这里规定为当前位置之前没有比他位置小的字符,就顺理成章地可以用拓扑排序

#include<bits/stdc++.h> using namespace std; const int M=1e4+4; int vis[30],visno[30]; char str[2],ans[M],s[M]; int tot,fuck[M*100],du[M*100],id[M]; vector<int>mp[30],g[M*100]; int main(){ int n,m; scanf("%d%d",&n,&m); int t=m*(m-1)/2; int flag=1; memset(vis,-1,sizeof(vis)); for(int i=1;i<=t;i++){ scanf("%s",str); int len; scanf("%d",&len); int c1=str[0]-'a'; int c2=str[1]-'a'; if(len==0){ visno[c1]=1; visno[c2]=1; continue; }scanf("%s",s); if(vis[c1]==-1){ int countt=0; for(int j=0;j<len;j++){ if(str[0]==s[j]){ id[j]=++tot; mp[c1].push_back(tot); fuck[tot]=c1; countt++; } } vis[c1]=countt; } else{ int countt=0; for(int j=0;j<len;j++){ if(s[j]==str[0]){ if(countt<mp[c1].size()) id[j]=mp[c1][countt]; countt++; } } if(countt!=vis[c1]) flag=0; } if(vis[c2]==-1){ int countt=0; for(int j=0;j<len;j++){ if(str[1]==s[j]){ id[j]=++tot; mp[c2].push_back(tot); fuck[tot]=c2; countt++; } } vis[c2]=countt; } else{ int countt=0; for(int j=0;j<len;j++){ if(s[j]==str[1]){ if(countt<mp[c2].size()) id[j]=mp[c2][countt]; countt++; } } if(countt!=vis[c2]) flag=0; } for(int j=0;j<len-1;j++){ g[id[j]].push_back(id[j+1]); du[id[j+1]]++; } } for(int i=0;i<m;i++){ if(vis[i]&&visno[i]) flag=0; } if(!flag||n!=tot) return puts("-1"),0; int cnt=0; //cout<<"!!"<<endl; queue<int>que; for(int i=1;i<=tot;i++) if(du[i]==0) que.push(i); while(!que.empty()){ int u=que.front(); que.pop(); ans[cnt++]=fuck[u]+'a'; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; du[v]--; if(du[v]==0){ que.push(v); } } } for(int i=1;i<=tot;i++) if(du[i]>0) return puts("-1"),0; ans[cnt]='