CoderForces Round54 (A~E)
题解:这一题读完题就写了吧。就是让你删除一个字母,使得剩下的字符组成的字符串的字典序最小;我们只要第一个当前位置的字符比下一个字符小的位置把该字符删去即可;
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define PI acos(-1.0) 4 #define RI register int 5 #define clr(a,b) memset(a,b,sizeof a) 6 typedef long long ll; 7 const int INF=0x3f3f3f3f; 8 const int maxn=2e5+10; 9 int n; 10 char str[maxn]; 11 int main() 12 { 13 scanf("%d",&n); 14 scanf("%s",str); 15 int len=strlen(str),temp=len-1; 16 for(int i=0;i<len-1;++i) 17 { 18 if(str[i]-str[i+1]>0) 19 { 20 temp=i; 21 break; 22 } 23 } 24 for(int i=0;i<len;++i) if(i!=temp) printf("%c",str[i]); 25 printf("\n"); 26 return 0; 27 }
ProblemB Divisor Subtraction
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll N; 5 int main() 6 { 7 cin>>N; 8 for(ll i=2;i*i<=N;++i) if(N%i==0) { printf("%lld\n",(N-i)/2+1);return 0; } 9 puts("1"); 10 return 0; 11 }
Problem C Meme Problem
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define clr(a,b) memset(a,b,sizeof a) 5 int main() 6 { 7 double a,b,d; 8 int t; 9 scanf("%d",&t); 10 while(t--) 11 { 12 scanf("%lf",&d); 13 double k=d*d-4*d; 14 if(0<d&&d<4) puts("N"); 15 else 16 { 17 a=(d+sqrt(k))/2; 18 b=(d-sqrt(k))/2; 19 printf("Y %.9f %.9f\n",a,b); 20 } 21 } 22 return 0; 23 }
Problem D. Edge Deletion
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int Maxn=3e5+10; 5 const LL INF=1e15; 6 int n,m,k,a[Maxn],f[Maxn],fa[Maxn]; 7 LL d[Maxn]; 8 bool boo[Maxn]; 9 struct qnode{ 10 int v; 11 LL cost; 12 bool operator < (const qnode &r) const {return cost>r.cost;} 13 }; 14 struct node{ 15 int v; 16 LL cost; 17 int w; 18 }; 19 vector<node> e[Maxn]; 20 set<int> s; 21 set<int>::iterator it; 22 23 void dijkstra() 24 { 25 for (int i=1; i<=n; i++) boo[i]=false,d[i]=INF; 26 priority_queue<qnode> q; 27 while(!q.empty()) q.pop(); 28 d[1]=0; 29 q.push(qnode{1,0}); 30 while (!q.empty()) 31 { 32 qnode temp=q.top();q.pop(); 33 int u=temp.v; 34 if (boo[u]) continue; 35 boo[u]=true; 36 for (int i=0,len=e[u].size();i<len;i++) 37 { 38 int v=e[u][i].v; 39 LL cost=e[u][i].cost; 40 if(!boo[v] && d[v]>d[u]+cost) 41 { 42 d[v]=d[u]+cost; 43 q.push(qnode{v,d[v]}); 44 f[v]=e[u][i].w; 45 fa[v]=u; 46 } 47 } 48 } 49 } 50 51 int main() 52 { 53 while(scanf("%d%d%d",&n,&m,&k)!=EOF) 54 { 55 for(int i=1; i<=n; i++) e[i].clear(); 56 for(int i=1; i<=m; i++) 57 { 58 int x,y,z; 59 scanf("%d%d%d",&x,&y,&z); 60 e[x].push_back(node{y,z,i}); 61 e[y].push_back(node{x,z,i}); 62 } 63 dijkstra(); 64 if(k>=n-1) 65 { 66 printf("%d\n",n-1); 67 for(int i=2; i<=n; i++) if (i!=n) printf("%d ",f[i]); else printf("%d\n",f[i]); 68 } 69 else 70 { 71 s.clear(); 72 for(int i=1; i<=n; i++) d[i]=0; 73 for(int i=2; i<=n; i++) d[fa[i]]++,s.insert(f[i]); 74 a[0]=0; 75 for(int i=1; i<=n; i++) if(d[i]==0) a[++a[0]]=i; 76 int x=n-1; 77 while(x>k) 78 { 79 int u=a[a[0]]; 80 a[0]--; 81 s.erase(f[u]); 82 d[fa[u]]--; 83 if(d[fa[u]]==0) a[++a[0]]=fa[u]; 84 x--; 85 } 86 printf("%d\n",x); 87 int i=0; 88 for(it=s.begin();it!=s.end();it++) 89 { 90 i++; 91 printf("%d",(*it)); 92 if(i==x) printf("\n"); else printf(" "); 93 } 94 } 95 } 96 return 0; 97 }
Problem E. Vasya and a Tree
题意:
给你一棵n个节点的树,每个点有一个权值,初始全为0,m次操作,每次三个数(v, d, x)表示只考虑以v为根的子树,将所有与v点距离小于等于d的点权值全部加上x,求所有操作完毕后,所有节点的值
首先要明确两件事情
性质1.每个人的操作只会影响到他的子孙(包括自己) 性质1.每个人的操作只会影响到他的子孙(包括自己)性质1.每个人的操作只会影响到他的子孙(包括自己)
性质2.每个人只会被他祖先的操作所影响(包括自己) 性质2.每个人只会被他祖先的操作所影响(包括自己)性质2.每个人只会被他祖先的操作所影响(包括自己)
也就是说,如果我们能在访问到某个节点时,统计出所有影响到该节点的祖先操作 也就是说,如果我们能在访问到某个节点时,统计出所有影响到该节点的祖先操作也就是说,如果我们能在访问到某个节点时,统计出所有影响到该节点的祖先操作
就可以统计出这个节点的最终权值 就可以统计出这个节点的最终权值就可以统计出这个节点的最终权值
而对于每个操作,我们只要用一个dep数组保存每个深度被增加的值 而对于每个操作,我们只要用一个dep数组保存每个深度被增加的值而对于每个操作,我们只要用一个dep数组保存每个深度被增加的值;
所有深度大于当前节点的操作都会影响到当前节点,如果用线段树就是一个区间求和问题 所有深度大于当前节点的操作都会影响到当前节点,如果用线段树就是一个区间求和问题所有深度大于当前节点的操作都会影响到当前节点,如果用线段树就是一个区间求和问题
为了减少代码量我们用树状数组,更新时只在本次操作的最深的深度更新 为了减少代码量我们用树状数组,更新时只在本次操作的最深的深度更新为了减少代码量我们用树状数组,更新时只在本次操作的最深的深度更新;
这样求一个1~maxdep的前缀和就是所有更新了根节点的操作 这样求一个1~maxdep的前缀和就是所有更新了根节点的操作这样求一个1~maxdep的前缀和就是所有更新了根节点的操作;
在求一个1~(nowdep-1)的前缀和就是所有不包含当前节点的操作 在求一个1~(nowdep-1)的前缀和就是所有不包含当前节点的操作在求一个1~(nowdep-1)的前缀和就是所有不包含当前节点的操作;两个前缀和相减就是当前节点被更新的值 两个前缀和相减就是当前节点被更新的值两个前缀和相减就是当前节点被更新的值;为了保证每个操作只影响自己子树内的节点,在dfs退出子树时 为了保证每个操作只影响自己子树内的节点,在dfs退出子树时为了保证每个操作只影响自己子树内的节点,在dfs退出子树时,要将当前根节点的所有修改值还原 要将当前根节点的所有修改值还原要将当前根节点的所有修改值还原。
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define clr(a,b) memset(a,b,sizeof a) 4 #define PI acos(-1.0) 5 #define lowbit(x) x&-x 6 typedef long long ll; 7 const int INF=0x3f3f3f3f; 8 const int maxn=3e5+10; 9 vector<int> G[maxn],dep[maxn],val[maxn]; 10 int n,m,v,d,x,y; 11 ll tree[maxn],ans[maxn]; 12 inline void readint(int &k) 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 17 k=x*f; 18 } 19 20 inline void add(int x,int val) 21 { 22 while(x<=n) 23 { 24 tree[x]+=val; 25 x+=lowbit(x); 26 } 27 } 28 29 inline ll sum(int x) 30 { 31 ll ans=0; 32 while(x) 33 { 34 ans+=tree[x]; 35 x-=lowbit(x); 36 } 37 return ans; 38 } 39 40 inline void dfs(int t,int fa,int depth) 41 { 42 for(int i=0;i<dep[t].size();++i) add(min(dep[t][i]+depth,n),val[t][i]); 43 ans[t]=sum(n)-sum(depth-1); 44 for(int i=0;i<G[t].size();++i) 45 { 46 if(G[t][i]==fa) continue; 47 dfs(G[t][i],t,depth+1); 48 } 49 for(int i=0;i<dep[t].size();++i) add(min(dep[t][i]+depth,n),-val[t][i]); 50 } 51 52 int main() 53 { 54 clr(tree,0);clr(ans,0); 55 readint(n); 56 for(int i=1;i<=n-1;++i) 57 { 58 readint(x),readint(y); 59 G[x].push_back(y);G[y].push_back(x); 60 } 61 readint(m); 62 for(int i=1;i<=m;++i) 63 { 64 readint(v),readint(d),readint(x); 65 dep[v].push_back(d); val[v].push_back(x); 66 } 67 dfs(1,0,1); 68 for(int i=1;i<=n;++i) printf("%lld%c",ans[i],i==n?'\n':' '); 69 return 0; 70 }