您的位置:首页 > 其它

Codeforces Round #396 (Div. 2)

2017-02-09 20:24 337 查看
比赛链接:Codeforces Round #396 (Div. 2)

A:找最长不公共连续子序列。显然若s!=t,输出s和t最大长度,否则输出-1.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
string s,t;
while(cin>>s>>t)
{
if(s.length()>t.length()) cout<<s.length()<<endl;
else if(s.length()<t.length()) cout<<t.length()<<endl;
else if(s==t) cout<<-1<<endl;
else cout<<s.length()<<endl;
}
return 0;
}


B:题意是给定若干个线段长度,求能否从中选出三条线段组成一个三角形。

先将线段长度L排序,若长度为x,y,z的线段能组成三角形,显然z+y>x&&z-y<x  ,设y的下标为i,那么用L[i-1]来替代x,L[i+1]来替代z,显然条件仍前述条件仍满足。

因此可以得出结论:如果存在三条线段能组成三角形,那么在数组L中,必然存在连续的三条线段能组成三角形,那么我们检验就行。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int l[100007];
bool check(int a,int b,int c)
{
if(a+b>c&&a+c>b&&b+c>a) return true;
else return false;
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++) cin>>l[i];
sort(l,l+n);
int i;
for(i=0;i<n-2;i++)
{

4000
if(check(l[i],l[i+1],l[i+2]))
{
puts("YES");
break;
}
}
if(i==n-2) puts("NO");
}

return 0;
}


C:题意是给定一个字符串,要求对字符串就行分割使得每对于每一个子串s,对于其中的每一个字符ch, a[ch]<=s.length() 。可以dp来做。

设dp[i]为串[0~i-1]能分割的方法数,len[i]为串[0~i-1]所能分割的最小子串数,并维护ans--整个串所能割出的最长子串的长度。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll dp[1007];
int a[26],len[1007],cnt[26],ans;
int f(char ch)
{
return ch-'a';
}
bool check(int l)
{
for(int i=0;i<26;i++)
if(cnt[i]&&l>a[i]) return false;
return true;
}
int main()
{
int n;
char s[1007];
while(cin>>n)
{
scanf("%s",s+1);
for(int i=0;i<26;i++) cin>>a[i];
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++) len[i]=1007;
ans=dp[0]=1;
len[0]=0;
for(int i=1;i<=n;i++)
{
memset(cnt,0,sizeof(cnt));
for(int j=i;j>0;j--)
{
cnt[f(s[j])]++;
if(check(i-j+1))
{
dp[i]=(dp[i]+dp[j-1])%mod;
ans=max(ans,i-j+1);
len[i]=min(len[i],len[j-1]+1);
}
else break;
}
}
cout<<dp
<<endl;
cout<<ans<<endl;
cout<<len
<<endl;
}
return 0;
}


D:题意是给定一些词汇,并描述他们之间的关系,将矛盾的关系忽略。并且之后给定两个词,并查询他们之间的关系。

可以用并查集来做,词汇i的同义词是i,反义词是i+n,根据输入进行合并操作就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
map<string,int> T;
int father[maxn<<1];
int f(int x)
{
if(x==father[x]) return x;
father[x]=f(father[x]);
return father[x];
}
void Union(int x,int y)
{
x=f(x);y=f(y);
father[x]=y;
}
int main()
{
ios::sync_with_stdio(false);
int n,m,q;
while(cin>>n>>m>>q)
{
T.clear();
int o;
string s,t;
for(int i=0;i<n;i++)
{
cin>>s;
T[s]=i;
}
for(int i=0;i<n*2;i++) father[i]=i;
for(int i=0;i<m;i++)
{
cin>>o>>s>>t;
int l=T[s],r=T[t];
if(o==1)
{
if(f(l+n)==f(r)||f(r+n)==f(l)) cout<<"NO"<<endl;
else
{
Union(l,r);
Union(l+n,r+n);
cout<<"YES"<<endl;
}
}
else
{
if(f(l+n)==f(r+n)||f(l)==f(r)) cout<<"NO"<<endl;
else
{
Union(l,r+n);
Union(r,l+n);
cout<<"YES"<<endl;
}
}
}
for(int i=0;i<q;i++)
{
cin>>s>>t;
int l=T[s],r=T[t];
if(f(l)==f(r)||f(l+n)==f(r+n)) cout<<1<<endl;
else if(f(l)==f(r+n)||f(l+n)==f(r)) cout<<2<<endl;
else cout<<3<<endl;
}
}
return 0;
}


E:题意是给定一个带权树,求Sum(Xor(Path(i,j)))  {i<=j}。 Xor(Path(i,j))为 a_i^a_p_1^a_p_2^....a_p_k^a_j , 其中 i,p_1,p_2,...p_k,j为i到j的路径上一次经过的点。

对于每一个点的权值 val, val=Sum(bit[j]*(1<<j)) 。因此可以将每一位孤立出来进行求和。答案为Sum(ans[j]*(1<<j)) 。

因此可以来跑dfs并对每一位进行树形dp,记ans[j]为有第j为多少条路径的异或值为1,dp[i][j][k]为点i的第j位异或值为k的路径数(其中i必为一端点)。dp可以简单地通过其孩子的dp值来进行转移。

但i可能有多棵子树,假设u,v是i的不同子树中的结点,u,v也同样地构成路径。对于子树t, s为同根的其他子树。  x=使得Xor(t,root,s)=1的t和s对应异或值和位数j的路径数量之积。ans[j]+=x/2 。

要更容易理解的话,就是将每一位剖离出来单独进行一次dfs,然后把每一位dfs的值求和即可。最关键的就是要求出异或值为1的路径总数量

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[100007][23][2];
ll ans[23];
vector<int> adj[100007];
int arr[100007][23];
int dfs(int u,int p)
{
ll t[23][2];
memset(t,0,sizeof(t));
for(int j=0;j<23;j++) dp[u][j][arr[u][j]]=1;
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i];
if(v==p) continue;
dfs(v,u);
for(int j=0;j<23;j++)
{
for(int k=0;k<2;k++)
{
dp[u][j][k]+=dp[v][j][k^arr[u][j]];
t[j][k]+=dp[v][j][k];
}
}
}
for(int j=0;j<23;j++)
{
ll x=0;
for(int i=0;i<adj[u].size();i++)
{
int v=adj[u][i];
if(p==v) continue;
for(int k=0;k<2;k++)
x+=(t[j][k]-dp[v][j][k])*dp[v][j][1^k^arr[u][j]];
}
ans[j]+=x/2;
}
for(int j=0;j<23;j++) ans[j]+=dp[u][j][1];
}
int main()
{
ios::sync_with_stdio(false);
int n,u,v;
int a;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a;
for(int j=0;j<23;j++)
{
arr[i][j]=a&1;
a>>=1;
}
}
for(int i=1;i<n;i++)
{
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
dfs(1,0);
ll sum=0;
for(int j=0;j<23;j++) sum+=(1<<j)*ans[j];
cout<<sum<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: