C、Distribution Center
theme:有n条流水线对应n个终点,m个机器,机器位于这n条线之间,可以将正两边的两条线上的货物交换,问最终每个终点可以有多少条线的货物传入?
solution:将机器按从小到大排序,则每个机器对应的两条流水线的终点上能传入的货物为这两条线之和。但每个间隔可能有多个机器,而下一次出现的机器直接相加会重复,所以每次记录下遍历时每个间隔的通过值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define far(i,n) for(int i=0;i<n;++i)
struct _a
{
int x,y;
bool operator<(const _a b)const
{
return x<b.x;
}
}a[100005];
int ans[200005];
int vis[200005];
int main()
{
int n,m;
cin>>n>>m;
far(i,m)
scanf("%d%d",&a[i].x,&a[i].y);
far(i,n)
ans[i]=1;
sort(a,a+m);
far(i,m)
{
ans[a[i].y-1]=ans[a[i].y-1]+ans[a[i].y]-vis[a[i].y-1];
ans[a[i].y]=vis[a[i].y-1]=ans[a[i].y-1];
}
far(i,n)
printf("%d ",ans[i]);
}
*D、Hidden Anagrams
theme:给定两个字符串A与B,问A、B的子 串中满足同字母异序的最大长度是多少?如A:anagram B: grandmother,答案为4:nagr与gran.
solution:暴力+字符串哈希。求出A所有子串的哈希值,放在map里,再算出B的子串在map里找有没有。由于这题不是真的找子串,而是找同字母异序,所以我们算出每个子串中a~z各有多少个来算哈希。
由于是结果匹配的A与B中的字串长度肯定相同,所以可以遍历长度,每找到A 中所有该长度的子串的哈希值就与B匹配,再清空map,避免MLE
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define far(i,t,n) for(int i=t;i<n;++i)
char a[4050],b[4050];
map<ull,ll>hashS;
map<ull,ll>::iterator it;
ull cnt[30];
ull p=1e9+7;
ull getHash()
{
ull ans=26;
far(i,0,26)
{
ans*=p;
ans+=cnt[i];
}
return ans;
}
int main()
{
scanf("%s%s",a,b);
int la=strlen(a),lb=strlen(b);
int l=min(la,lb);
int ans=0;
for(int i=1;i<=l;++i)
{
hashS.clear();
memset(cnt,0,sizeof(cnt));
for(int j=0;j<i;j++)
cnt[a[j]-'a']++;
for(int j=0;i+j<la;++j)
{
hashS[getHash()]++;
cnt[a[j]-'a']--;
cnt[a[i+j]-'a']++;
}
hashS[getHash()]++;
memset(cnt,0,sizeof(cnt));
for(int j=0;j<i;j++)
cnt[b[j]-'a']++;
for(int j=0;i+j<lb;++j)
{
if(hashS[getHash()])
ans=max(ans,i);
cnt[b[j]-'a']--;
cnt[b[i+j]-'a']++;
}
if(hashS[getHash()])ans=max(ans,i);
}
printf("%d\n",ans);
return 0;
}
*G、Placing Medals on a Binary Tree
theme:有一棵无穷深的完全二叉树,深度从0开始,即根节点深度为0.有n次操作,每次给定一个深度x,代表在一个深度为x的结点放置一个模型,要求从根节点到任意一个模型的路径中不会经过其它模型。对于这n次操作,每次询问该操作是否能执行,是输出YES,不是输出NO。1 ≤ n ≤ 5 × 10^5,1<=x<=10^9
solution:由题意知如果在结点i放置了一个模型,则i的所有子节点和父节点都不能再放置了。简单地可以考虑 算出每层的结点数,没放置一个结点就相应减去它 的子、父节点层能放置的数目,但x范围很大,这样明显不行。
由于这是完全二叉树,我们可以考虑模拟二进制。从深度为1开始,放置一个结点,则下一层只有两个选择了:左子树或右子树,接下来深度为3的也只有两个选择了...即在有上i层的约束下,i+1层只有两个选择。所以我们可以记录下目前为止,从深度为1到深度为i连续的最长的每层都放置了一个的个数cnt(即若深度为1~4的层都有一个模型,深度为5的层没放置模型,则cnt=4)
每次操作判断cnt与x大小:
(1)cnt>x
则说明前cnt层都已经放了一个了,x层不可能再放了。NO
(2)cnt=x
前面的层都放了的情况下,最多有两个选择,此时判断一下该层已经放了几个即可。且一旦该层放满两个,则不可能再放到任何结点了。
(3)cnt<x
说明从cnt层到x层中间有空的层,