1 /* 2 CF#190DIV.1-C 3 题意:给你n个结点的树,给这些结点标记字母AB..Z,对于标记相同的结点路径上 4 的结点的标记必须有一个是大于该标记的;问是否可以标记(A是最大标记) 5 6 分析:整天思路就是找一个点,然后标记为最大标记i,然后再分别以最大标记i+1,标记该点的子树 7 依次递归;最终如果标记<=Z就是可以的; 8 因为只有10^5个点,最长情况下需要logn个不同的标记对于n个结点的树(成一条链) 9 2^26>log(10^5) 所以必定有解; 10 11 而那个点,最优的应该就是树的重心,重心的定义:去掉这个点后,树给分成a个连通分量,每个连通分量 12 仍然是一棵树,并且a个连通分量中最大结点数最小; 13 14 求法:这棵树的结点树为all,dfs()下去,同时记录该结点每棵子树的结点个数,那么该结点的 15 父亲结点那棵子树的结点树就是all-sum_soncnt-1; 16 用di[i]表示结点i的子树中结点个数最大的数,那么di[]最小的那个点就是重心 17 18 */ 19 #include<cstdio> 20 #include<cstring> 21 #include<iostream> 22 #include<cmath> 23 #include<algorithm> 24 #include<cstdlib> 25 #include<vector> 26 using namespace std; 27 const int N=100000+10; 28 vector<int> edge[N]; 29 int n; 30 int how[N]; 31 int di[N]; 32 void read(){ 33 memset(how,-1,sizeof(how)); 34 for (int i=0;i<=n;i++) edge[i].clear(); 35 for (int i=0;i<n-1;i++){ 36 int u,v;scanf("%d%d",&u,&v); 37 edge[u].push_back(v); 38 edge[v].push_back(u); 39 } 40 } 41 42 int son_cnt[N]; 43 void find_center(int rt,int fa,int &id,int all){ 44 int sum=1,tmp=0; 45 for (int i=0;i<edge[rt].size();i++){ 46 int c=edge[rt][i]; 47 if (how[c]!=-1 || c==fa) continue; 48 find_center(c,rt,id,all); 49 sum+=son_cnt[c]; 50 tmp=max(tmp,son_cnt[c]); 51 } 52 di[rt]=max(tmp,all-sum); 53 if (id==-1 || di[id]>di[rt]) id=rt; 54 son_cnt[rt]=sum; 55 } 56 void findall(int rt,int fa,int &all){ 57 all++; 58 for (int i=0;i<edge[rt].size();i++){ 59 int c=edge[rt][i]; 60 if (how[c]!=-1 || c==fa)continue; 61 findall(c,rt,all); 62 } 63 } 64 void work(int rt,int tar){ 65 int all=0; 66 findall(rt,-1,all); 67 68 int id=-1; 69 find_center(rt,-1,id,all); 70 71 how[id]=tar; 72 for (int i=0;i<edge[id].size();i++){ 73 int c=edge[id][i]; 74 if (how[c]!=-1) continue; 75 work(c,tar+1); 76 } 77 78 } 79 int main(){ 80 while (~scanf("%d",&n)){ 81 read(); 82 work(1,0); 83 for (int i=1;i<n;i++){ 84 printf("%c ",how[i]+'A'); 85 }printf("%c\n",how[n]+'A'); 86 } 87 return 0; 88 }
1 /* 2 CF#190DIV.1-B 3 题意:看过游戏王的人的知道,现在轮到你攻击了,问你能给对方照成的最大伤害是多少 4 一次有效的攻击必须是己方的怪兽的攻击力大于等于对方的攻击了; 5 对方怪兽成防御状况攻击没有伤害,成攻击状况伤害为己方攻击减去对方攻击力 6 7 分析:题解里有很多种方法,贪心,dp,最小费用最大流 8 下面是贪心:分两类,一类是能达到直接攻击的方案,一类是不能达到直接攻击的方案 9 10 写代码遇到的问题: 11 下面代码中标记为$的那一行代码,位置放到了下面标记@的位置,导致当n3==0时,并且 12 前一组数据使v2[0]>v3[0],导致样例跑挂,这个错误很难找出来,如果没有数据的话, 13 所以如果清空的代价很小,那么能清空的就清空,该早点判断就早点判断 14 15 */ 16 #include<cstdio> 17 #include<cstring> 18 #include<iostream> 19 #include<cstdlib> 20 #include<algorithm> 21 #include<cmath> 22 #include<vector> 23 using namespace std; 24 typedef long long LL; 25 const int N=100+10; 26 int n,m; 27 int f[N],v1[N],v2[N]; 28 int ans; 29 int work(){ 30 int flag1=0; 31 int v3[N],v4[N],n3=0,n4=0; 32 for (int i=0;i<n;i++){ 33 if (f[i]==1) v3[n3++]=v1[i]; 34 else v4[n4++]=v1[i]; 35 } 36 sort(v3,v3+n3); sort(v4,v4+n4); 37 int vis[N]; 38 memset(vis,0,sizeof(vis)); 39 sort(v2,v2+m); 40 int j=0; 41 for (int i=0;i<m;i++){ 42 if (j==n3) break;//$ 43 if (v2[i]>v3[j]){ 44 vis[i]=1; 45 j++; 46 } 47 /*if (j==n3) break;@*/ 48 } 49 if (j!=n3) flag1=1; 50 j=0; 51 for (int i=0;i<m;i++){ 52 if (j==n4) break; 53 if (vis[i]==0){ 54 if (v2[i]>=v4[j]){ 55 j++; 56 } 57 58 } 59 } 60 if (j!=n4) flag1=1; 61 62 int sum1=0,sum2=0; 63 for (int i=0;i<m;i++) if (vis[i]==0) sum1+=v2[i]; 64 for (int i=0;i<n4;i++) sum2+=v4[i]; 65 if (flag1==0)ans=max(ans,sum1-sum2); 66 67 j=m-1; 68 int tmp=0; 69 for (int i=0;i<n4;i++){ 70 if (v2[j]>=v4[i]) { 71 tmp+=v2[j]-v4[i]; 72 j--; 73 } 74 } 75 ans=max(ans,tmp); 76 cout<<ans<<endl; 77 78 } 79 int main(){ 80 // cout<<4%0<<endl; 81 while (cin>>n>>m){ 82 char s[10]; 83 ans=0; 84 for (int i=0;i<n;i++){ 85 scanf("%s%d",s,v1+i); 86 if(s[0]=='A') f[i]=0; 87 else f[i]=1; 88 } 89 for (int i=0;i<m;i++) scanf("%d",v2+i); 90 work(); 91 } 92 93 return 0; 94 }
1 /* 2 CF#190DIV.1-A 3 题意:一个机器人站在原地(0,0)给你一串只包含UDLR的字符串,机器人只能按照这个串的顺序 4 来前进,并且可以无限次重复,问时候可以到达(a,b); 5 6 分析:有一些trick,比如循环的次数只能是正数,不能除零 7 还是刚开始就分类分清楚的好,不然代码中的一些逻辑真得搞不清楚 8 9 */ 10 #include<cstdio> 11 #include<cstring> 12 #include<cstdlib> 13 #include<iostream> 14 #include<cmath> 15 #include<cstdio> 16 #include<algorithm> 17 using namespace std; 18 typedef long long LL; 19 const int N=100+10; 20 char s[N]; 21 const int nx[4]={0,0,-1,1}; 22 const int ny[4]={1,-1,0,0}; 23 LL a,b; 24 LL X,Y; 25 void init(){ 26 X=Y=0; 27 for (int i=0;s[i];i++){ 28 int j; 29 if (s[i]=='U') j=0; 30 else if (s[i]=='D') j=1; 31 else if (s[i]=='L') j=2; 32 else if (s[i]=='R') j=3; 33 X+=nx[j]; Y+=ny[j]; 34 } 35 } 36 void work(){ 37 int tx=0,ty=0; 38 int flag=0; 39 for (int i=0;s[i];i++){ 40 if (X==0 && Y==0){ 41 if (a==tx && b==ty) flag=1; 42 }else if (X==0 && Y!=0){ 43 if (a==tx && (b-ty)%Y==0 && (b-ty)/Y>=0) flag=1; 44 }else if (X!=0 && Y==0){ 45 if (b==ty && (a-tx)%X==0 && (a-tx)/X>=0) flag=1; 46 }else if (X!=0 && Y!=0){ 47 if ((a-tx)%X==0 && (b-ty)%Y==0 && (a-tx)/X==(b-ty)/Y && (a-tx)/X>=0) flag=1; 48 } 49 if (flag) break; 50 int j; 51 if (s[i]=='U') j=0; 52 else if (s[i]=='D') j=1; 53 else if (s[i]=='L') j=2; 54 else if (s[i]=='R') j=3; 55 tx+=nx[j]; ty+=ny[j]; 56 } 57 puts(flag?"Yes":"No"); 58 } 59 int main(){ 60 while (cin>>a>>b){ 61 scanf("%s",s); 62 init(); 63 work(); 64 } 65 66 return 0; 67 }