A.生成树
思路:贪心。
一开始用写了个假算法,发现数据太弱了。
以第一棵树为基准,我们用记录每条边,规定
,这样方便去重。
然后我们只需在第二课树找到第一棵树中不存在的边即可,因为第二棵树少的边和多的边数肯定相等的,不然边数和不可能为,所以根据贪心我们只需统计少的边即可,这样用
就很方便了,此时
的大小是:
,
是相重的个数,
我们需要的答案是,所以答案是:
。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
set<PII>s;
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u>v) swap(u,v);
s.insert(make_pair(u,v));
}
int ans=0;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
if(u>v) swap(u,v);
s.insert(make_pair(u,v));
}
printf("%d\n",s.size()-(n-1));
return 0;
}B.七彩线段
思路:状态压缩。
看到最大只有
,可以想到用一个数的二进制表示状态。
我们可以设前
个线段为状态
的最大长度。
当不用第个线段时,显然有状态转移:
。
当用第个线段时,我们需要找到最后一个小于
的线段,这一步可以排序后二分查找。
令找到的位置为。
令新状态:
然后求中
的个数为
个的最大值即可。
对于求二进制中的1可以递推求。
.
意思是删掉
最右边的1.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int dp[N][130];
struct line{
int l,r,c;
bool operator<(const line&l)const{
return r<l.r;
}
}a[N];
int b[N],n,m,cnt[130];
void pre(int n){
cnt[0]=0;
for(int i=1;i<=n;i++) cnt[i]=cnt[i&(i-1)]+1;
}
int solve(){
int ans=-1;
memset(dp,-1,sizeof dp);
dp[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<128;j++){
dp[i][j]=max(dp[i][j],dp[i-1][j]);
int p=lower_bound(b+1,b+n+1,a[i].l)-b-1;
if(~dp[p][j]){
dp[i][j|(1<<(a[i].c-1))]=max(dp[i][j|(1<<(a[i].c-1))],dp[p][j]+a[i].r-a[i].l);
//printf("dp[%d][%d]=%d\n",p,j,dp[p][j]);
//printf("i=%d,j|x=%d\n",i,j|(1<<(a[i].c-1)));
}
if(cnt[j]==m)
ans=max(ans,dp[i][j]);
}
return ans;
}
int main(){
pre(128);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].c);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++) b[i]=a[i].r;
printf("%d\n",solve());
return 0;
}C.成绩分析
思路:签到题,对于平均值,我们只需将所有数求和,然后除以即可,对于中位数,我们需要特判一下,如果是奇数,我们直接取中间的一个数,如果是偶数,就取中间的两个数的平均值,最后再将中位数和平均数,求绝对值差即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int a[N];
int main(){
int n,b=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
b+=a[i];
}
b/=n;
int x;
if(n&1) x=a[n/2];
else x=(a[n/2-1]+a[n/2])/2;
printf("%d\n",abs(b-x));
return 0;
}D.刺客信条
思路:优先队列。
考虑:以到达时间较短的方格优先进入队列,然后从起点开始,把起点丢入队列,开始跑一遍,因为我们是以时间较短优先,所以最先到达终点的就是用时最少的了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
char a[N][N];
int n,m,d[4][2]={0,1,0,-1,1,0,-1,0},vis[N][N],b[N][N];
int sx,sy,ex,ey;
struct node{
int x,y,d;
bool operator <(const node& no)const{
return d>no.d;
}
}now;
int bfs(int x,int y){
priority_queue<node>q;
q.push({x,y});
vis[x][y]=1;
while(!q.empty()){
now=q.top();q.pop();
//printf("(%d,%d)=%d\n",now.x,now.y,now.d);
if(now.x==ex&&now.y==ey) return now.d;
for(int i=0;i<4;i++){
int nx=now.x+d[i][0],ny=now.y+d[i][1];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!vis[nx][ny]){
int h=now.d+b[nx][ny];
vis[nx][ny]=1;
q.push({nx,ny,h});
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("\n%c",&a[i][j]);
if(a[i][j]=='S') sx=i,sy=j;
else if(a[i][j]=='E') ex=i,ey=j;
else if(a[i][j]=='A'||a[i][j]=='B'||a[i][j]=='C') b[i][j]=100;
else b[i][j]=a[i][j]-'0';
}
printf("%d\n",bfs(sx,sy));
return 0;
}E.我不爱她
思路:。
才发现是多校里的题目,之前太菜了不会,发现只需要代码改动一下就行了。
还是一样,考虑预处理所有字符串的后缀,用存起来,然后每个字符串作为前缀时的贡献,因为要满足最长的后缀也即最长的前缀,所以对于较短的重复的前缀我们要删去一些贡献,比如
。
对于来说,后缀的个数
为
,但是实际上只有第一个字符串
能与其匹配。
所以中的
要减去较长的出现的前缀,即
的个数为
。
所以的贡献实际上为
个。
这一步可以用实现,因为
中的
数组就代表的最长前后缀的长度。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=998244353;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false),cin.tie(0)
string s[N];
int nt[N];
unordered_map<ull,int>mp;
int ans[N],base=233;
void kmp(string s){
nt[0]=0;
for(int i=1,j=0;i<s.size();i++){
while(j&&s[i]!=s[j]) j=nt[j-1];
if(s[i]==s[j]) j++;
nt[i]=j;
}
}
void Hash(string s)
{
ull t=0,p=1;
for(int i=s.size()-1;i>=0;i--){
t+=p*(s[i]-'a'+1);
p*=base;
mp[t]++;
}
}
int n;
int main(){
IOS;
int t;
cin>>t;
while(t--){
cin>>n;
mp.clear(),mst(ans);
ll res=0;
for(reg int i=0;i<n;i++) cin>>s[i],Hash(s[i]);
for(reg int i=0;i<n;i++){
ull t=0;
for(reg int j=0;j<s[i].size();j++){
t=t*base+s[i][j]-'a'+1;
ans[j]=mp[t];
}
kmp(s[i]);
for(reg int j=0;j<s[i].size();j++){
if(nt[j]) ans[nt[j]-1]-=ans[j];
}
for(reg int j=0;j<s[i].size();j++)
res+=1LL*ans[j]*(j+1);
}
cout<<res<<endl;
}
return 0;
}

京公网安备 11010502036488号