Codeforces Round #754 (Div. 2)
tip3
给定一个长度为 n 的字符串,只包含 a、b、ca、b、c,求满足以下条件的最短的子串的长度:
- 长度至少为2
- aa 的数量严格大于 bb 的数量
- aa 的数量严格大于 cc 的数量
如果无解,输出 -1
很容易想到:aa aba aca abca
这三种序列如果有的话就选最优就行
但是.....考虑不全面!!
认真思考,当上述序列不存在,
abbacca
accabba就是最优情况
枚举就行
经验:贪心题:一定考虑所有情况,想全面,这很考察思维,需要锻炼
Codeforces Round #754 (Div. 2) - Virtual Judge (vjudge.net)
tip4
数学知识
先入为主
首先想到性质:
legal(u,v)当且仅当high(u)==high(v)
如果想让A这个人一定赢,下第一步,那我让任意两个节点之间都illegal不就可以了??
这样一定最优秀(不用想那么多,直接想最优的)
染色法,
把0和1的节点存着
神奇的构造!
计算出tot(0):100111001
那么我在分的时候
(以此类推)把最高位是100000000的数都拿出来,
有100000000-111111111刚好100000000个
说明如果按照这种构造方式,一定而且恰好可找到tot(0)个数,使得所有最高位分解恰好在{0}集合里
那么,万一不够呢?(n<111111111)
这就需要我们用min的一类颜色先分配,然后其他的就都给另一类就行
const int N=2000+100; int ans[200000+100];//存每个点对应后来的哪个点 vector<int>col[3]; vector<int>belong[40];//0或者1 struct node { int to,nxt; }e[400000+100]; int tot,head[200000+100]; inline void add(int x,int y) { e[++tot].to=y,e[tot].nxt=head[x],head[x]=tot; } inline int get(int x) { int tmp=0; while(x) { tmp++;x>>=1; } return tmp; } int n; inline void dfs(int x,int fa,int c) { col[c].push_back(x); for(int i=head[x];i;i=e[i].nxt) { int to=e[i].to; if(to==fa)continue; dfs(to,x,c^1); } } inline void solve() { tot=0; _f(i,0,n)head[i]=0; _f(i,0,31)belong[i].clear(); _f(i,0,1)col[i].clear(); n=re(); _f(i,1,n)belong[get(i)].push_back(i); _f(i,1,n-1) { int u=re(),v=re();add(u,v);add(v,u); } dfs(1,-1,0); int top=col[0].size(); int tip=get(n); //chu("(top)%d(tip:%d)\n",top,tip); f_(i,tip,1)//为什么倒着?? { int num=belong[i].size(); if(top>=num) { top-=num; while(num--) { ans[col[0].back()]=belong[i].back(); //chu("ans:%d %d\n",col[0].back(),belong[i].back()); belong[i].pop_back(); col[0].pop_back(); } } } // _f(i,0,1)chu("col1:%d\n",col[1][i]); f_(i,tip,1) { int num=belong[i].size(); while(num--) { ans[col[1].back()]=belong[i].back(); belong[i].pop_back(); col[1].pop_back(); } } _f(i,1,n)chu("%d ",ans[i]); chu("\n"); } int main() { // freopen("exam.txt","r",stdin); // freopen("a.out","w",stdout); int t=re(); while(t--)solve(); return 0; }