第一次這麼順手。。。都是1A。。。。D想了1個小時,想了一個假算法。。。最後20分開E,我叼,簡單DP???不負衆望的10分鐘A掉。。。node
A. Yet Another Dividing into Teams 只會有兩個隊c++
B1.B2. Books Exchange直接DFS找環,環內的傳遞時間是同樣的。標記一下,線性複雜度。算法
C1. Good Numbers (easy version) 其實就是3進製表示形式不能有2,那麼簡單版本直接預處理1-1000而後找第一個大於n的數便可。ide
#include<bits/stdc++.h> #define LL long long using namespace std; vector<int>ans; bool check(int x){ int flag=0; while(x){ if (x%3==2){ flag=1; break; } x=x/3; } if (flag==1)return 0; else return 1; } void init(){ for (int i=1;i<=19683;i++){ if(check(i)){ ans.push_back(i); } } } int main(){ int t,n; scanf("%d",&t); init(); while(t--){ scanf("%d",&n); int pos=lower_bound(ans.begin(),ans.end(),n)-ans.begin(); printf("%d\n",ans[pos]); } return 0; }
C2. Good Numbers (hard version) 咱們比較容易求出最大小於n的數,由於咱們能夠從3的高位往低位試。而後從地位到高位,把第一個3進制位爲0的位置變成1,其後位置所有變成0,就是恰好大於等於n的三進制沒有2的。spa
#include<bits/stdc++.h> #define LL long long using namespace std; LL n; LL qpow(LL a,LL b) { LL ans=1; while(b) { if(b&1) ans=ans*a; a=a*a; b=b/2; } return ans; } int vis[50]; int main() { int t; LL s=1e18; scanf("%d",&t); while(t--) { scanf("%lld",&n); LL ans=0; memset(vis,0,sizeof(vis)); for (int i=38;i>=0;i--) { if (ans+qpow(3,i)<n){ ans+=qpow(3,i); vis[i]=1; } } for (int i=0;i<=38;i++){ if (vis[i]==1){ ans-=qpow(3,i); }else { ans+=qpow(3,i); break; } } printf("%lld\n",ans); } return 0; }
D1.D2. Too Many Segments 看錯題了,我一直覺得要保證整個區間是連續的。。。。發現其實只要區間的覆蓋次數<k次就行,這樣的話,其實就很簡單了,把區間排序,放入一個mutilset裏面,裏面維護全部有相交區間的覆蓋,而後判斷mutilset是否是大於k個,若是是必定要丟,怎麼丟比較優雅???反正最左邊已經保證了覆蓋次數<k,那麼丟區間的右端點最遠的,這樣對後面影響也最小。3d
#include<bits/stdc++.h> #define pii pair<int,int> #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) #define mp make_pair #define pb push_back using namespace std; const int maxx = 2e5+6; multiset<pii>s; vector<int>ans; struct node{ int l,r,id; }p[maxx]; bool cmp(node a,node b){ return a.l<b.l; } int main(){ int n,k; while(~scanf("%d%d",&n,&k)){ for (int i=1;i<=n;i++){ scanf("%d%d",&p[i].l,&p[i].r); p[i].id=i; } ans.clear(); sort(p+1,p+1+n,cmp); rep(i,1,n){ ///s裏面最小的r小於p[i].l表明二者已經不相連了 while(s.size() && (*s.begin()).first<p[i].l)s.erase(s.begin()); s.insert(mp(p[i].r,p[i].id)); ///這裏s表明重複裏面每一段都有重複部分 若是重複部分大於K了 ///確定刪除最右邊的,由於最左邊的已經知足小於k了,刪除最右邊的,使得後面出現>k的機率變小了 while(s.size()>k){ auto it=s.end(); it--; ans.pb((*it).second); s.erase(it); } } int sz=ans.size(); printf("%d\n",sz); for (int i=0;i<sz;i++){ if(i)printf(" %d",ans[i]); else printf("%d",ans[i]); } printf("\n"); } return 0; }
E.簡單DP,每層必定是由上一層轉移過來,因此很簡單了。code
#include<bits/stdc++.h> #define LL long long #define lson rt<<1 #define rson rt<<1|1 using namespace std; const int maxx = 2e5+6; LL a[maxx]; LL b[maxx]; LL n,c; LL dp[maxx][3]; int main(){ while(~scanf("%lld%lld",&n,&c)){ for (int i=2;i<=n;i++){ scanf("%lld",&a[i]); } for (int i=2;i<=n;i++){ scanf("%lld",&b[i]); } dp[1][1]=0; dp[1][2]=c; for (int i=2;i<=n;i++){ dp[i][1]=min(dp[i-1][1]+a[i],dp[i-1][2]+a[i]); dp[i][2]=min(dp[i-1][2]+b[i],dp[i-1][1]+b[i]+c); } for (int i=1;i<=n;i++){ if (i-1)printf(" %lld",min(dp[i][1],dp[i][2])); else printf("0"); } printf("\n"); } }
F.真~神仙題,樹有點權,問選出一個集合,使得集合內部全部點的距離>=k,而且點權和最大。。。blog
樹形DP作法。。。看了2個小時自閉了。。。等牛逼網友發博客再說排序
貪心:咱們考慮選擇某個的貢獻,咱們首先安裝深度從下往上進行遍歷,而後對於每次選擇i,咱們把這個點全部距離<=k的點,減去a[i],表明選擇了這個點,若是某個點的值>0,表明這個點比i更優秀???咱們能夠直接加上a[j]表明選擇j,因爲咱們算的是貢獻,因此直接把周圍的點的全部能到的點的所有減去便可。博客
#include<bits/stdc++.h> #define LL long long #define pii pair<int,int> #define mp make_pair #define pb push_back using namespace std; const int maxx = 1005; int ver[maxx],Next[maxx],head[maxx]; int vis[maxx]; int a[maxx]; int n,k,tot; vector<int>b; void add(int x,int y){ ver[++tot]=y;Next[tot]=head[x];head[x]=tot; ver[++tot]=x;Next[tot]=head[y];head[y]=tot; } void bfs(int st){ queue<pii>q; q.push(mp(st,0)); while(q.size()){ int u=q.front().first; int dep=q.front().second; b.pb(u); q.pop(); vis[u]=1; for (int i=head[u];i;i=Next[i]){ int v=ver[i]; if (!vis[v]){ q.push(mp(v,dep+1)); } } } } int dfs(int x){ for (int i=1;i<=n;i++){ vis[i]=0; } queue<pii>q; while(q.size())q.pop(); q.push(mp(x,0)); int c=a[x]; while(q.size()){ int u=q.front().first; a[u]-=c; vis[u]=1; int dep=q.front().second; q.pop(); for (int i=head[u];i;i=Next[i]){ int v=ver[i]; if (vis[v])continue; if (dep<k){ q.push(mp(v,dep+1)); } } } return c; } int main(){ while(~scanf("%d%d",&n,&k)){ for (int i=1;i<=n;i++){ scanf("%d",&a[i]); } int uu,vv; for (int i=1;i<n;i++){ scanf("%d%d",&uu,&vv); add(uu,vv); } bfs(1); reverse(b.begin(),b.end()); int sz=b.size(); int ans=0; for (int i=0;i<sz;i++){ if (a[b[i]]>0)ans+=dfs(b[i]); } printf("%d\n",ans); } return 0; }