转载请注明出处,谢谢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;
}