转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
这场比赛整体不难。
A:直接统计,比较
B:3个部分,其中有两个地方需要注意
第三部分可能不存在,那么最后那个“/”就不需要
另外 一个就是httprururu这种情况,容易输出http://.ru/ruru,注意.ru之前是必须有的。
C:反向贪心
D:两个位的与为1,那么这两位都为1,所以把与a[i]有关的或起来
E:如果是+则加一个进来 ,如果是-则减掉一个,判断最值的差
F:就是时间的处理
G:直接暴力
struct Edge { int v,next; }e[N]; map<string,int>mp; vector<string>name; int start[N],tot; void _add(int u,int v) { e[tot].v=v;e[tot].next=start[u]; start[u]=tot++; } void addedge(int u,int v) { _add(u,v); _add(v,u); } int main() { int m,cnt=0,tot=0; mem(start,-1); cin>>m; while(m--){ string s1,s2; cin>>s1>>s2; if(mp.find(s1)==mp.end()) { mp[s1]=cnt++; name.pb(s1); } if(mp.find(s2)==mp.end()) { mp[s2]=cnt++; name.pb(s2); } int u=mp[s1],v=mp[s2]; addedge(u,v); } cout<<cnt<<endl; for(int i=0;i<cnt;i++) { bool vis[N]; mem(vis,false); for(int j=start[i];j!=-1;j=e[j].next) vis[e[j].v]=true; vis[i]=true; int ans=0,mmax=-1; for(int k=0;k<cnt;k++) { if(vis[k]) continue; int c=0; for(int j=start[k];j!=-1;j=e[j].next) if(vis[e[j].v]) c++; if(c>mmax)mmax=c,ans=1; else if(c==mmax) ans++; } cout<<name[i]<<" "<<ans<<endl; } return 0; }
H:Dshawn比赛的时候用数状数组过了,ORZ
DP可解。
先预处理,ok[i][j]即str[i...j]是否为回文,这一步,n^2搞定。
然后sum[i][j]处理以i----j区间内,以j结尾的回文的有多少个
然后dp[i][j]表示i----j区间内的回文有多少个,就是在sum的基础上,把不以j结尾的也算上
预处理O(N^2),查询O(1)
short ok[N][N]; int ans[N][N],sum[N][N]; char str[N]; int main() { while(cin>>str) { mem(ok,0); mem(ans,0); mem(sum,0); int l=strlen(str); for(int i=1;i<=l;i++) { for(int j=0;j<l-i+1;j++) { if(i==1) ok[j][j]=1; else if(i==2) ok[j][j+i-1]=str[j]==str[i+j-1]; else ok[j][j+i-1]=ok[j+1][j+i-2]&&(str[j]==str[i+j-1]); } } for(int i=0;i<l;i++) { sum[i][i]=ok[i][i]; for(int j=i+1;j<l;j++) sum[i][j]=sum[i][j-1]+ok[i][j]; } for(int i=0;i<l;i++) { ans[i][i]=ok[i][i]; for(int j=i-1;j>=0;j--) ans[j][i]=ans[j+1][i]+sum[j][i]; } int L,R,q; cin>>q; while(q--) { cin>>L>>R; L--;R--; cout<<ans[L][R]<<endl; } } return 0; }