千年可贵一见,我竟然没翻车???
awa
c++
成功进入了rank3,然鹅。。。
ui
前8名全是前3。。。
妙趣横生awa
只要拿到了基础分的200,就是前3awa
哦对了,T4是本来的T1。。
T1是本来的T2,T2是本来的T3,T3是本来的T4
老师昨天题目加错了。。。
因此就一大群人A了T4 awa
快乐
spa
T1code
睿爸喜欢搭塔塔。blog
睿爸有h2个高度为n1的红色砖块,和n2个高度为h2的蓝色砖块,这些的砖块的底面和顶面的长宽均相同,且你不能将这些砖块立体旋转或者转动。字符串
睿爸能够按照以下方式搭塔:get
1.每一个砖块要么能够放在地面上,要么必须垒在一个颜色不一样的砖块上面(一个砖块上面仅能够放一个砖块)。string
2.至少须要一个砖块,没必要用完全部的砖块。it
睿爸想知道这样最多能够搭出多少个不一样高度的塔。io
给出n1,n2,h1,h2
简单题,可是要long,long
直接给结论,随便推一推就行了
#include <bits/stdc++.h> #define ll long long using namespace std ; ll a,b,x,y,ans; inline ll read() { register ll Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } int main() { freopen("tower.in","r",stdin); freopen("tower.out","w",stdout); a=read();x=read(); b=read();y=read(); if(a>b) { swap(a,b); } if(x==y) { ans+=a*2; } else { ans+=a*3; } if(a!=b)ans++; cout<<ans<<endl; return 0; }
T2
题目的意思很是的补坑描述,我看了5分钟才看懂。。。
就是要你在一个字符串里面在找出一个子序列(不用连续,可是要求顺序不能倒)
取出之后,本来的序列要求变成取出的序列的一个排列,就是有且仅有取出的序列的所有字符
本来吧,若是真的是只有我说的这些要求,那就是一道简单题.
若是把题目里面的字典序最小去掉,我分分钟就能A了它,惋惜去不得
显然,子序列T的合法要求就是,在原序列S中,每一个字符出现的次数必须是T中出现的次数的两倍,不然必定不合法。
因此要若是不要保证字典序最小,这题就讲完了。。。
淦
awa
其实后面也不难搞,只用按位贪心一下,每一位都要贪心的选出可以保证后面合法的,且字典序最小的方案。
由于字典序自己就是一种贪心。。。
若是是判断一个字母是否合法,只须要判断前面字母使用的次数和用完之后还有几个剩余,就是正解了
awa
#include <bits/stdc++.h> #define ll long long using namespace std ; inline ll read() { register int Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } int s[27],ss[27],ans[27][210],m=0,n; char ch[210]; void cherk() { for(int i=0;i<26;ss[i]=s[i],i++) { if(s[i]%2!=0) { puts("Clbtxdy!"); exit(0); } } } void work() { for(int i=1;i<=n;i++) { int mx=0; for(int j=i;j<=n;j++) { int x=ch[j]-'a'; bool ff=0; for(int k=0;k<26;k++) { if(x==k) { if(ans[k][j]>s[k]/2+1) { ff=1; break; } } else { if(ans[k][j]>s[k]/2) { ff=1; break; } } } if(!ff && ss[ch[j]-'a']>0) { if(mx==0) { mx=j; } else { if(ch[j]-'a'<ch[mx]-'a') { mx=j; } } } } if(mx==0) mx=i; cout<<ch[mx]; ss[ch[mx]-'a']-=2; s[ch[mx]-'a']+=2; m++; if(m==n/2) { exit(0); } i=mx; } } int main() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); scanf("%s",ch+1); n=strlen(ch+1); for(int i=1;i<=n;i++) { s[ch[i]-'a']++; for(int j=0;j<26;j++) { if(ch[i]-'a'!=j) { ans[j][i]=ans[j][i-1]; } else { ans[j][i]=ans[j][i-1]+1; } } } cherk(); work(); return 0; }
T3
是个博弈论
这个问题,有一个很麻烦的地方,就是若是是个dp的话,它的状态会十分的复杂,由于我要同时去考虑两种状态:1.睿爸的。2.杜教的。
可是考虑到咱们最后的答案,其实要求的就是杜教扣了睿爸多少,因此就能够把睿爸取到的数先所有都加上(包括杜教的),而后再减去所有的数(只有杜教的),这就是答案。
其中的A是睿爸能取到的数。
U是全集
因此咱们要作的事情其实就是最大化a[i]+b[i]。
那就很好搞啦!
可是这个并无到达博弈论的部分。
这只是为了方便去计算咱们的答案罢了
如今问题已经被简化了,咱们来讨论一下博弈的策略。
由于答案和栈中的元素有关,而栈也是只有两个元素,因此这不就是在叫着:“讨论我!讨论我!”吗。。。
对于一个栈的价值,其实就是如咱们上面说的,a[i]+b[i]。这个就是为何先推出来上面的式子。
这个让咱们讨论价值这件事情变得可能。
结论1:若是一个栈的价值a+b<=c+d,先手永远只能拿到上面的,然后手总能拿到下面的。
证实1:若是先手拿了一个栈顶,那么后手必定是能够直接拿栈底的
那若是他没拿呢?
那先手就是憨。
由于没拿,就说明了另外一个栈顶的元素确定是要比这个栈底大的。根据咱们的前提条件,先手拿的栈顶的元素是比栈顶小的。
拿为何先手不拿这个栈顶呢?它不香吗?
证毕。
awa
因而咱们就快乐的排除掉了a+b<=c+d的栈。由于他们的贡献是十分显然的。
接下来考虑一下a+b>c+d的栈。
结论2:对于a+b>c+d的栈,确定是前后手交替拿取目前最大的元素
证实2:
由于前面证实了最优的策略就是使拿到的元素两个值相加起来最大。
因此咱们确定是要先拿取最大是元素的。
由于所有的栈都已是a+b>c+d了,因此不会存在冲突的状况。
这样就行了啊awa
ac!awa
#include <bits/stdc++.h> #define ll long long using namespace std ; ll a[200001],b[200001],c[200001],d[200001],n;bool vis[200001]; ll ans1,ans2; inline ll read() { register ll Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } int main() { freopen("dortmund.in","r",stdin); freopen("dortmund.out","w",stdout); n=read(); for(ll i=1;i<=n;i++) { a[i]=read();b[i]=read(); c[i]=read();d[i]=read(); } for(ll i=1;i<=n;i++) { if(a[i]+b[i]<=c[i]+d[i]) { ans1+=a[i]+b[i]; } } priority_queue<pair<ll,ll> > q; for(ll i=1;i<=n;i++) { if(a[i]+b[i]>c[i]+d[i]) { q.push(make_pair((a[i]+b[i]),i)); } } ll awsd=1; while(q.size()!=0) { // cout<<1<<endl; pair<ll,ll> x=q.top(); ll now=x.first; if(awsd==1) { ans1+=now; awsd=2; } else { awsd=1; } if(vis[x.second]==false) { q.push(make_pair((c[x.second]+d[x.second]),x.second)); vis[x.second]=true; } q.pop(); } for(ll i=1;i<=n;i++) { ans1-=b[i]; ans1-=d[i]; } cout<<ans1<<endl; return 0; }
呼~总算是写完了awa
T4
一看就是图论题(逃
一看就是最短路awa
这个嘛。。。
不就是最短路和dp的结合题吗。。。
很典型啊。。。
最短路嘛,是有状态的,因此像这总多了一个限制条件的问题,我想应该是可以用加一维状态的办法来解决的。
啥不行就给啥加状态awa(逃
其实老是加状态也是不行的,由于时空间复杂度撑不住啊awa
仍是要看状况的awa
这个题解我是真的看不懂。。。
直接放上来吧。。。
说的我好迷啊awa
淦,原来是我没写过几道分层图的dp。。。
我说为何我最短路配dp老是不会写。。。
淦
不写了,补坑去了awa
代码用了机房dalao lsf的神奇dfs,跑的比正解还快,并且好写。。。
本质就是一个朴素的dfs。。。。
code
#include <bits/stdc++.h> #define ll long long using namespace std; struct edge { ll to,next,v;bool f; }e[10001]; ll head[10001],tot,n,m,k;bool vis[10001],vis2[10001];int dis[1001][20],ans=INT_MAX; inline ll read() { register ll Q=0,f=1;register char C=getchar() ; while(C<'0'or C>'9')f=C=='-'?-1:1,C=getchar() ; while(C<='9'and C>='0')Q=(Q<<1)+(Q<<3)+C-'0',C=getchar() ; return f*Q; } void add(int i,int j,int v,bool flag) { e[++tot].next=head[i]; e[tot].to=j; head[i]=tot; e[tot].v=v; e[tot].f=flag; } void dfs(int x,int sum,int cnt) { if(cnt>k) { return ; } if(vis[x]==true) { ans=min(ans,sum); return ; } if(sum>=dis[x][cnt]) { return ; } vis[x]=true; dis[x][cnt]=sum; for(int i=head[x];i!=0;i=e[i].next) { int u=e[i].to; dfs(u,sum+e[i].v,cnt+(e[i].f?1:0)); } vis[x]=false; } int main() { freopen("trolley.in","r",stdin); freopen("trolley.out","w",stdout); n=read();m=read();k=read(); for(int i=1;i<=n;i++) { int x=read(),y=read(),v=read(); add(x,y,v,false); } for(int i=1;i<=abs(m-n);i++) { int x=read(),y=read(),v=read(); add(x,y,v,true); } memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=k;i++) { dis[0][i]=0; } dfs(1,0,0); cout<<ans<<endl; return 0; }
the end 撒花awa