T1
/*
思路:对于每一对L,R,标记[L,R)(注意左闭右开!),
并且求出最小的L(minl)和最大的R-1(maxr);
循环maxl~maxr,若被标记则最长连续挤奶时间+1,最长无人挤奶时间=0;
否则最长连续挤奶时间=0,最长无人挤奶时间+1,同时更新最大值。
*/
#include<bits/stdc++.h>
using namespace std;
int n;
int sum1,sum2,ans1=-1e9,ans2=-1e9;
int minl=1e9,maxr=-1e9;
bool vis[1000031];
int main(){
cin>>n;
for(int i=1,l,r;i<=n;i++){
cin>>l>>r;
minl=min(minl,l),maxr=max(maxr,r-1); //求minl和maxr
for(int i=l;i<r;i++) vis[i]=1; //标记
}
for(int i=minl;i<=maxr;i++){ //统计最长连续挤奶时间
if(vis[i]) sum1++;
else sum1=0;
ans1=max(ans1,sum1);
}
for(int i=minl;i<=maxr;i++){ //统计最长无人挤奶时间
if(!vis[i]) sum2++;
else sum2=0;
ans2=max(ans2,sum2);
}
cout<<ans1<<' '<<ans2<<'\n';
return 0;
}
T2
/*
思路:考虑贪心,设第n+1个金币在(0,0)位置,避免特判,
并且对所有金币按y坐标排序;
对于第i个与第i+1个金币,若x[i+1]-x[i]>y[i+1]-y[i](即需要走的时间大于下落时间),则立即输出Notabletocatch;
否则,若一直未出现此情况,输出Abletocatch。
*/
#include<bits/stdc++.h>
using namespace std;
int T,n;
struct node{
int x,y;
}a[131];
bool check(){
for(int i=1;i<=n;i++){
if(abs(a[i+1].x-a[i].x)>abs(a[i+1].y-a[i].y)) //若需要走的时间大于下落时间
return 0;
}
return 1;
}
bool cmp(node a,node b){
return a.y<b.y;
}
string work(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y;
a[n+1].x=0,a[n+1].y=0; //将第n+1枚硬币设为(0,0)
sort(a+1,a+n+2,cmp); //按y坐标排序
return check()?"Abletocatch\n":"Notabletocatch\n";
}
int main(){
cin>>T;
while(T--) cout<<work();
return 0;
}
T3
/*
枚举k的值,对于每一个k,枚举子串起点并截取子串,
若一直没有出现过就输出当前的k即可。
*/
#include<bits/stdc++.h>
using namespace std;
int n;
map<string,bool> vis;
string s;
int main(){
cin>>n>>s;
for(int i=1;i<=n;i++){ //枚举k的值
bool f=1;
vis.clear(); //清空map
for(int j=0;j+i-1<s.size();j++){ //枚举子串起点,注意不能超过n
string t=s.substr(j,i); //截取子串
if(vis[t]){ f=0; break; } //若出现过了
vis[t]=1; //标记
}
if(f){ cout<<i; break; } //若一直未出现输出当前的k
}
return 0;
}
T4
/*
思路:尝试将方程变为kx+b=0的形式,其中k为系数,b为常数,x为未知数。这样方程的结果为(-b)/k。
具体的,首先记录变量sgn、eq、num、hasnum,表示符号、在等式的哪一边、当前数字、刚才是否拼接了数字。
扫描一遍方程式,若si为-,则常数+=num*eq*sgn,并令sgn=-1,hasnum=num=0。+、=时同理。
若si为数字,则令num=num*10+(si-'0'),并令hasnum=0;
若si为字母,则若hasnum=1,则令系数+=num*eq*sgn,并令num=0;
否则,直接令系数+=eq*sgn。
并且需要令未知数字母=si,且hasnum=0。
*/
#include<bits/stdc++.h>
using namespace std;
string s;
bool hasnum; //刚才是否拼接数字
int sgn=1,eq=1,num; //符号、等号的哪一边、数字
double ans; //答案
char x; //字母
int b,k; //常数和系数
int main(){
cin>>s;
for(int i=0;s[i];i++){
if(s[i]=='-'){ //符号类
b+=eq*sgn*num;
num=0,sgn=-1,hasnum=0;
}
if(s[i]=='+'){
b+=eq*sgn*num;
num=0,sgn=1,hasnum=0;
}
if(s[i]=='='){
b+=eq*sgn*num;
num=0,sgn=1,eq=-1,hasnum=0;
}
if(isdigit(s[i])) //数字类
num=num*10+(s[i]-'0'),hasnum=1;
if(islower(s[i])){ //字母类
x=s[i];
if(hasnum){ //刚刚拼接过数字
k+=eq*sgn*num;
num=0;
}
else
k+=eq*sgn;
hasnum=0;
}
}
b+=eq*sgn*num; //注意加上最后的常数
ans=(double)-b/(double)k; //计算答案
if(ans==-0.0) ans=0; //特判
cout<<x<<'='<<setprecision(3)<<fixed<<ans;
return 0;
}
T5
/*
思路:所有牛能看到的牛的个数的总和,等于所有牛被看到的次数的总和。
同时,能看见这头牛的牛一定比这头牛高。
因此,我们考虑维护一个栈,里面的元素从栈顶到栈底单调递增,
这样就保证了从栈底到栈顶的每一头牛都能看见上面的所有牛。
于是每当有一头牛将要入栈时,就将身高<=它的牛全部弹出,
并将答案加上栈的大小(就是这头牛被看到的次数),再入栈即可。
这就是著名的单调栈算法,时间复杂度O(n)。
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,ans;
stack<int> s;
signed main(){
cin>>n;
for(int i=1,x;i<=n;i++){
cin>>x;
while(!s.empty()&&x>=s.top()) s.pop(); //只要栈不为空,弹出身高<=当前牛的。
ans+=s.size(); //答案累加栈的大小
s.push(x); //入栈
}
cout<<ans;
return 0;
}