*PS:为什么我t5死活都调不出来呢(눈‸눈)

T1:原创,参考noip火柴排队。
T2: codevs 2178 表达式运算Cuties (我自己找的)
T3:Codeforce867E(865D) Buy Low Sell High
T4: USACO 2015 DEC Gold  不明链接1   不明链接2
( 该网站不提供在线测评,仅提供数据下载。考试使用原数据。)
T5:原创。





T1 原创 火柴排队的改编版

一说到火柴排队,应该就会做了。(好巧 这个题我前些天才看过qwq)。

解法:
对于B中的每个字符都统计下他在A中出现的位置,存入一个数组里,这个位置就是它最后要移到的位置。最后对这个数组求一个逆序对,逆序对的数量就是最少需移动的步数。
不能的情况就是B和A的字符种类或数量不同,输入时处理。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;int N,ans,cnt,Cnt;
int a[110],used[1000],b[110];
char c[110];
struct maple{int pos;char a;
}A[110],B[110];bool cmp(maple c,maple d)
{return c.a<d.a;
}void hebing(int l,int mid,int r)
{int i=l,j=mid+1,k=l-1;while(i<=mid&&j<=r){if(a[i]<=a[j]) b[++k]=a[i],++i;else b[++k]=a[j],ans+=mid-i+1,++j;}while(i<=mid) b[++k]=a[i],++i;while(j<=r)  b[++k]=a[j],++j;for(int i=l;i<=r;++i)a[i]=b[i];
}
void Mergesort(int l,int r)
{if(l==r) return ;int mid=(l+r)>>1;Mergesort(l,mid);Mergesort(mid+1,r);hebing(l,mid,r);
}
int main()
{freopen("order.in","r",stdin);freopen("order.out","w",stdout);scanf("%d",&N);scanf("%s",c);for(int i=0;i<N;++i){A[i].a=c[i],A[i].pos=i;if(!used[c[i]]) ++cnt;++used[c[i]];}scanf("%s",c);for(int j=0;j<N;++j){B[j].a=c[j],B[j].pos=j;--used[c[j]];if(!used[c[j]]) ++Cnt;if(used[c[j]]<0) Cnt=-110;}if(cnt==Cnt){sort(A,A+N,cmp);sort(B,B+N,cmp);for(int i=0;i<N;++i)a[B[i].pos]=A[i].pos;Mergesort(0,N-1);cout<<ans;}else cout<<-1;return 0;
}


T2 简单的栈应用

注意处理负数的情况,判断栈空的函数一定要放在最前面。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
using namespace std;int k[100],f=1;
char a[210];
stack<long long> num;
stack<char> opt;void Done()
{char x=opt.top();opt.pop();long long a=num.top();num.pop();long long b=num.top();num.pop();long long c=0;if(x=='+') c=a+b;if(x=='-') c=b-a;if(x=='*') c=b*a;if(x=='/') c=b/a;if(x=='^') {c=1;while(a){c*=b;--a;}}num.push(c);
}
int main()
{freopen("formula.in","r",stdin);freopen("formula.out","w",stdout);scanf("%s",a);k['+']=k['-']=1;k['*']=k['/']=2;k['^']=3;k['(']=4;num.push(0);long long l=strlen(a),Num=0;a[l]=')';for(int i=0;i<=l;++i){if(a[i]>='0'&&a[i]<='9') Num=Num*10+(a[i]-'0'),Num*=f,f=1;else{if(Num!=0) num.push(Num); Num=0;if(a[i]=='-'&&a[i-1]=='(') {f=-1;continue;}if(a[i]==')'){while(!opt.empty()&&opt.top()!='(')   Done();if(!opt.empty()) opt.pop();}else if(opt.empty()||opt.top()=='('||k[a[i]]>k[opt.top()])      opt.push(a[i]);else {while(!opt.empty()&&opt.top()!='('&&k[a[i]]<=k[opt.top()]) Done();opt.push(a[i]);}}}while(!opt.empty()&&opt.top()!='(') Done();cout<<num.top();return 0;
}



T3 看似DP的贪心

是不是很像之前的一道有N天每天可买可卖可不作处理的dp问题??

但是那个题有个限制就是每天手里最多持有一份股票,而这个题则是多份的。

因为这个题是t3而之前又做过类似的题,所以我马上就在想dp的路上一去不复返了QAQ。。。

最后确实打出来了,测的时候却显示MLE!!!因为long long的数组开的太大!!! 好吧。。。最后知道long long 在128MB下也就能开个1600万+。。。

定义 f[i][j]表示到第i天手里有j份股票所赚到的最多的钱数

可知

   f[i][j]=max(f[i][j],f[i-1][j]);         // 不作处理f[i][j]=max(f[i][j],f[i-1][j+1]+P[i]);  // 卖出f[i][j]=max(f[i][j],f[i-1][j-1]-P[i]);  //买入

改完后可以过5个点

DP代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
const int Cn=300000+10;int N;
long long P[Cn],f[4000][4000];int main()
{freopen("resell.in","r",stdin);freopen("resell.out","w",stdout);scanf("%d",&N);for(int i=1;i<=N;++i) scanf("%lld",&P[i]);for(int i=1;i<=N;++i)for(int j=0;j<=N;++j){f[i][j]=-1e9+7;if(j<=i) {if(i!=1){f[i][j]=max(f[i][j],f[i-1][j]);f[i][j]=max(f[i][j],f[i-1][j+1]+P[i]);if(j-1>=0) f[i][j]=max(f[i][j],f[i-1][j-1]-P[i]);} else f[1][0]=0,f[1][1]=-P[1];}}cout<<f[N][0];return 0;
}

emmmm。。。如果用滚动数组优化的话可以过6个点,就是另开一个数组先记录一下f[i-1]的值用来更新。。。这里就不给出代码了。

正解 ·贪心

来自loi.Sherlock的题解总结(就是讲题时我做的笔记啊qwq,略长)

emmm...要赚的钱最多,我们肯定是低价买入,高价买出。。大体上想想:可以维护一个小根堆,每过一天,用当天的价格和堆顶比较,如果价格大于堆顶,ans就加上*当天价格-堆顶价格*,弹出堆顶;如果小于等于,就加入堆。但是这个做法有一个bug,举个栗子:2 5 10 按照我们现在的贪心做法,答案应该是 5-2=3 (每天只能操作一次),但是正确答案应该是 10-2=8这就很尴尬了。。。(划掉)这时我们发现 10-2=(10-5)+(5-2) ,这是不是代表我可以利用一下5呢??对于 a<b<c 的情况,我要利用中介b ,就把b放一个进去(之前是b>a时,只统计ans,b并没有被放入)用来做中介。但是这样还有一个bug 如 2 5 10 7   输出 10-5+5-2=8 ,但正确答案是 10-2+7-5=10我们发现之前的5实际上并没有被用到,反而被弹出了。解决的方法就是一开始就放上两个5,一个做中介,一个用来更新答案。所以对之前贪心做法的改进就是当我遇到一个比堆顶大的元素时,更新ans,弹出堆顶,同时放入两个当前价格,对答案不会有影响。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;int N;
long long ans=0;
int P[300010];priority_queue<int,vector<int>,greater<int> >q;int main()
{freopen("resell.in","r",stdin);freopen("resell.out","w",stdout);scanf("%d",&N);for(int i=1;i<=N;++i){scanf("%d",&P[i]);if(!q.empty()&&P[i]>q.top()){ans+=P[i]-q.top();q.pop();q.push(P[i]);}q.push(P[i]);}printf("%lld",ans);return 0;
}



T4 无比麻烦的BFS

注意特判啊!!我做的时候WA,TLE,MLE真是够了!

注意紫色的格子上的移动方向是与之前进入的方向有关的,并不是可以随便走的!! 所以要另开一维记录前进的方向,但是并不是每个格子的前进方向都要记录,只需记录紫色格子的,不然会TLE。。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int mxn=1000+5;int N,M,f;
int x[4]={0,1,0,-1},  //  0--> 右 1--> 下 2--> 左 3-->上 y[4]={1,0,-1,0};
int A[mxn][mxn];
int used[mxn][mxn][2][5];
struct maple{int x,y,z,face,d;
};
queue<maple>q;  // 手打队列会mle bool can(int k,maple a,int K)
{int X=a.x+x[k],Y=a.y+y[k];if(X<=0||X>N||Y<=0||Y>M||used[X][Y][a.z][K]) return false;if(A[X][Y]==0) return false;    if(A[X][Y]==3&&!a.z) return false;return true;
}
void Bfs()
{q.push((maple){1,1,0,0,0});used[1][1][0][4]=1;while(!q.empty()){maple a=q.front();q.pop();if(a.x==N&&a.y==M)  {f=1;printf("%d",a.d);return ;}if(A[a.x][a.y]==4){int face=a.face;int X=a.x+x[a.face],Y=a.y+y[a.face];if(A[X][Y]!=4) face=4;  // 记录每个格子的方向会T if(used[X][Y][a.z][face]) continue;if(can(a.face,a,face)){int xx=a.x+x[a.face],yy=a.y+y[a.face],z=a.z,d=a.d+1;if(A[xx][yy]==2) z=1,used[xx][yy][0][face]=1;   // 不加会T 1q.push((maple){xx,yy,z,face,d});used[xx][yy][z][face]=1;continue;}}for(int i=0;i<4;++i){int xx=a.x+x[i],yy=a.y+y[i],face=i;if(A[xx][yy]!=4) face=4; if(can(i,a,face)){int z=a.z,d=a.d+1;if(A[xx][yy]==4) z=0;if(A[xx][yy]==2) z=1,used[xx][yy][0][face]=1;  //不加会T 2q.push((maple){xx,yy,z,face,d});used[xx][yy][z][face]=1;}}}
}
int main()
{freopen("cowboy.in","r",stdin);freopen("cowboy.out","w",stdout);scanf("%d%d",&N,&M);for(int i=1;i<=N;++i)for(int j=1;j<=M;++j)scanf("%d",&A[i][j]);Bfs();if(!f) cout<<-1;return 0;
}//*PS:注释的都是血的教训。。。QAQ




T5 十分明显的exgcd??

再次%%%原创题dalao @loi.MurasameKatana

由于这个题我还是没能调出来,所以我打算十分不要脸的打算粘上题解和std_(:з」∠)_ 。。。。ε=ε=ε=┌(; ・_・)┘跑

而对于本题,首先我们将起点到所有城镇的距离(最短路)排序,每次选取存在妖刀且路程之和为当前最小的两个城镇中的妖刀,取其攻击力为a b,结界初始防御值-临界防御值为c,那么两把妖刀各自的使用次数为方程的解x,y那么我们首先通过exgcd()求出一组解满足ax + by = gcd(a,b)注:exgcd()求出的特解为 |x| + |y| 最小的一组解然后得到满足ax + by = c的解,再推导其他的解找到:两个使用次数大于0,使用方案不会使任意一把妖刀折断,且消耗的磨损值之和最小的解。这便是T5胧村正的算法过程然后就是注意细节处理by  Loi_MurasameKatana

(侵删)

Std

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define RI register int
using namespace std;
typedef long long ll;
const int INF =1000000007;
ll n,m,h,p,ru,rv,rw,tot,x,y,xs,ys,ans,anz,A,Z,minx,f;
ll dis[100010],first[200010],nxt[200010],c[100010],r[100010],k[100010],t[100010],num[100010];
bool flag;
bool inq[100010],unb[100010];
struct edge
{ll u,v,w;
}l[400010];
queue<int>q;
inline bool cmp(ll a,ll b)
{if(dis[a]!=dis[b])return dis[a]<dis[b];else return a<b;
}
inline void build(ll f,ll t,ll c)
{l[++tot]=(edge){f,t,c};nxt[tot]=first[f];first[f]=tot;
}
inline bool check_1(ll a,ll b,ll c)//分情况讨论边界条件
{if(a>0&&b>0){if(xs<=0||ys>(k[num[c]]/r[num[c]]))return 0;}else if(a>0&&b<0){if(xs>(k[num[c-1]]/r[num[c-1]])||ys>(k[num[c]]/r[num[c]]))return 0;}else if(a<0&&b>0){if(xs<=0||ys<=0)return 0;}else if(a<0&&b<0){if(xs>(k[num[c]]/r[num[c]])||ys<=0)return 0;}return 1;
}
inline bool check_2(ll a,ll b,ll c)
{if(a>0&&b>0){if(xs>(k[num[c-1]]/r[num[c-1]])||ys<=0)return 0;}else if(a>0&&b<0){if(xs<=0||ys<=0)return 0;}else if(a<0&&b>0){if(xs>(k[num[c-1]]/r[num[c-1]])||ys>(k[num[c]]/r[num[c]]))return 0;}else if(a<0&&b<0){if(xs<=0||ys>(k[num[c]]/r[num[c]]))return 0;}return 1;
}
inline void SPFA()
{for(RI i=1;i<=n;i++)dis[i]=INF;dis[1]=0;q.push(1);inq[1]=1;while(!q.empty()){int k=q.front();q.pop();inq[k]=0;for(RI i=first[k];i!=-1;i=nxt[i]){ll x=l[i].v;if(dis[x]>dis[k]+l[i].w){dis[x]=dis[k]+l[i].w;if(!inq[x]){q.push(x);inq[x]=1;}}}}
}
inline ll exgcd(ll a,ll b,ll &x,ll &y)
{if(b==0){x=1;y=0;return a;}ll d=exgcd(b,a%b,x,y);ll t=x;x=y;y=t-a/b*y;return d;
}
int main()
{freopen("blade.in","r",stdin);freopen("blade.out","w",stdout);memset(first,-1,sizeof(first));scanf("%lld%lld%lld%lld",&n,&m,&h,&p);for(RI i=1;i<=m;i++){scanf("%lld%lld%lld",&ru,&rv,&rw);build(ru,rv,rw);build(rv,ru,rw);}for(RI i=1;i<=n;i++){scanf("%lld%lld%lld%lld",&c[i],&r[i],&k[i],&t[i]);if(t[i]==1)c[i]*=-1;if(!c[i]&&!r[i]&&!k[i]&&!t[i])unb[i]=1;}SPFA();for(RI i=1;i<=n;i++)if(unb[i]==1)dis[i]=INF;for(RI i=1;i<=n;i++)num[i]=i;sort(num+1,num+n+1,cmp); // 给城镇排序 minx=1e9+7;for(RI i=2;i<=n;i+=2){if(unb[num[i-1]]||unb[num[i]]) // 若搜遍周边城镇也没有找到 break;ll d=exgcd(c[num[i-1]],c[num[i]],x,y);//ax+by=gcd(a,b) if(!d||(h-p)%d!=0)  //%0RE 若无解 continue;ll s=(h-p)/d;//asx+bsy=c x*=s;y*=s;if(x<y){swap(x,y);swap(c[num[i-1]],c[num[i]]);swap(r[num[i-1]],r[num[i]]);swap(k[num[i-1]],k[num[i]]);}int li=x;int lr=y;for(RI j=0;;j++)//j>=0 {xs=x-(c[num[i]]/d)*j;//xs=x-b/d*jys=y+(c[num[i-1]]/d)*j;//ys=y+a/d*jif(!check_1(c[num[i-1]]/d,c[num[i]]/d,i))break;if(xs>0&&ys>0&&xs<=(k[num[i-1]]/r[num[i-1]])&&ys<=(k[num[i]]/r[num[i]]))//合法情况,使用次数大于0且未达次数上限 {if(((xs*r[num[i-1]]+ys*r[num[i]])<minx)||(A!=0&&Z!=0&&(xs*r[num[i-1]]+ys*r[num[i]]==minx)&&(abs(xs*r[num[i-1]]-ys*r[num[i]])<abs(A*r[num[i-1]]-Z*r[num[i]]))))//取磨损值消耗之和最小的方案 {//若存在多解取磨损值相差最小的 minx=(xs*r[num[i-1]]+ys*r[num[i]]);A=xs;Z=ys;flag=1;//存在合法解}}}x=li;y=lr;for(RI j=-1;;j--)//j<0{xs=x-(c[num[i]]/d)*j;ys=y+(c[num[i-1]]/d)*j;//x为大正数,y为大负数的情况不会导致非法退出if(!check_2(c[num[i-1]]/d,c[num[i]]/d,i))break;if(xs>0&&ys>0&&xs<=(k[num[i-1]]/r[num[i-1]])&&ys<=(k[num[i]]/r[num[i]])){if(((xs*r[num[i-1]]+ys*r[num[i]])<minx)||(A!=0&&Z!=0&&(xs*r[num[i-1]]+ys*r[num[i]]==minx)&&(abs(xs*r[num[i-1]]-ys*r[num[i]])<abs(A*r[num[i-1]]-Z*r[num[i]])))){minx=(xs*r[num[i-1]]+ys*r[num[i]]);A=xs;Z=ys;flag=1;}}}if(flag){ans=min(A*r[num[i-1]],Z*r[num[i]]);//统计 anz=max(A*r[num[i-1]],Z*r[num[i]]);break;}}if(flag){printf("%lld %lld\n",ans,anz);}else printf("Game over\n");return 0;
}

The end.

队内胡策 2017.10.24 求逆序对+表达式计算+贪心+Bfs+最短路、exgcd相关推荐

  1. 【队内胡策】2017.10.15

    难忘的一天. T1 DQS 捡石子 题目描述 今年开始上学的 DQS 非常喜欢石子, 她总是会收集很多不同类型 的石子来卖钱, 这个世界的石子只有两种--蓝色和白色(用 01 表示) 并且都是连在一起 ...

  2. 【队内胡策 11.1】 T1 T2

    至于我为什么把两个题放一起,看题就知道了: T1 O(T*3√p),10^8,正好卡时 啥也不说,代码: #include<iostream> #include<cstdio> ...

  3. szu 寒训第二天 树状数组 二维树状数组详解,以及树状数组扩展应用【求逆序对,以及动态第k小数】

    树状数组(Binary Index Tree) 树状数组可以解决可以转化为前缀和问题的问题 这是一类用以解决动态前缀和的问题 (有点像线段树简版) 1.对于 a1 + a2 + a3 + - + an ...

  4. 树状数组的相关知识 及 求逆序对的运用

    文章目录 树状数组概念 前缀和和区间和 树状数组原理 区间和--单点更新 前缀和--区间查询 完整代码 离散化 sort函数 unique函数去重 erase函数仅保留不重复元素 通过树状数组求逆序对 ...

  5. wikioi 1688 求逆序对

    /*=========================================================== wikioi 1688 求逆序对 时间限制: 1 s 空间限制: 12800 ...

  6. 分治法:归并排序求逆序对

    现给出这个定义,什么是逆序对,NOIP火柴排队这个题是逆序对的一个比较好的例题,这里我们只讨论求逆序对的一些高效的算法 一般有归并排序以及树状数组两种方法,本文只讨论归并排序求逆序对 这里不给出原理只 ...

  7. HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...

  8. Tido 习题-二叉树-树状数组求逆序对

    这里给大家提供一个全新的求逆序对的方法 是通过树状数组来实现的 题目描述   样例输入 Copy 5 2 3 1 5 4 样例输出 Copy 3 提示       #include<iostre ...

  9. P3531 [POI2012]LIT-Letters(求逆序对)

    题目传送门:https://www.luogu.com.cn/problem/P3531 题意 给出只包含大写字母的字符串 A 和字符串 B,每次可以交换字符串 A 两个相邻的字符,求 A 变成 B ...

最新文章

  1. HDU1531(差分约束+Bellman_ford)
  2. 树状数组(Binary Indexed Tree) 总结
  3. Android IOS WebRTC 音视频开发总结(十)-- webrtc入门002
  4. 在vs2010中使用nuget安装EF5报错解决方案
  5. Ambari 架构(三)Ambari Server 架构
  6. php制作留言板的题_PHP实现留言板功能实例代码
  7. 2021年下半年网络工程师上午真题及答案解析
  8. Ubuntu下安装中文输入法
  9. 王栋: 要做好推荐,只有技术是不够的
  10. 拓端tecdat|用R语言中的神经网络预测时间序列:多层感知器和极限学习机
  11. 硅谷新传奇Kevin Systrom
  12. 获取高德地图位置的经纬度
  13. 查看Andriod内置浏览器WebView版本
  14. 用cocos实现的《我的世界》已经上线微信小游戏,分享一下主要技术
  15. folly库安装(5)folly的安装
  16. 【C#】KPM算法解决字符串匹配问题
  17. 解决错误 Could not find method leftShift() for arguments
  18. 20本英文书点亮你的人生智慧
  19. 如何在互联网中隐藏自己
  20. 淘宝开网店的详细教程

热门文章

  1. IOC控制反转的三种方式
  2. OSSIM下添加oracle listener.log
  3. Java中实现文件更名操作
  4. Springboot过滤器和拦截器详解及使用场景
  5. 关税降低 平台抢生意: 海外代购往哪走?
  6. 面汤增强记忆 菜汤抗污染
  7. 蓝桥杯 扑克牌“魔术
  8. pycharm版本控制和数据库管理
  9. opencv-python教程学习系列8-opencv图像算术运算
  10. 腾讯开源框架Hippy综述