因为思念新宿的"小姐姐"们,岛娘计划6月份再去一趟东京,不过这次看来她需要自掏腰包。经过了几天的夜战,岛娘终于在体力耗尽之前,用Python抓下了所有6月份,上海至东京的全部共 n 张机票。现在请你帮助债台高筑的岛娘筛选出符合时间区间要求的,最贵的机票。
输入数据的第一行包含两个整数 n, m(1 ≤ n, m ≤ 105),分别表示机票的总数,和询问的总数。接下来的 n 行,每行两个整数 t, v (1 ≤ t, v ≤ 105),表示每张机票出发的时间和价格。 接下来的 m 行,每行两个整数 a, b (1 ≤ a ≤ b ≤ 105),表示每个询问所要求的时间区间。
对于每组询问,输出一行表示最贵的价格。如果没有符合要求的机票,输出一行"None"。
7 6 1 1 2 1 4 3 4 4 4 5 6 9 7 9 1 7 1 2 6 7 3 3 4 4 5 5
9 1 9 None 5 None
题目链接→1299 打折机票
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-4 using namespace std; const int N = 100005; const int M = 100000; const int inf = 100000; const int mod = 2009; struct tree { int left,right,Max; }s[4*N]; int a[N]; void buildtree(int l,int r,int p) { s[p].left=l,s[p].right=r; if(l==r) { s[p].Max=a[l]; return ; } int mid=(l+r)/2; buildtree(l,mid,p*2); buildtree(mid+1,r,p*2+1); s[p].Max=max(s[p*2].Max,s[p*2+1].Max); } int search(int l,int r,int p) { if(l<=s[p].left&&s[p].right<=r) return s[p].Max; int mid=(s[p].left+s[p].right)/2; if(l>mid) return search(l,r,p*2+1); else if(r<=mid) return search(l,r,p*2); else return max(search(l,mid,p*2),search(mid+1,r,p*2+1)); } int main() { int n,m,i,t,v,l,r,ans; while(~scanf("%d%d",&n,&m)) { memset(a,0,sizeof(a)); for(i=1;i<=n;i++) { scanf("%d%d",&t,&v); a[t]=max(a[t],v); } buildtree(1,n,1); for(i=0;i<m;i++) { scanf("%d%d",&l,&r); ans=search(l,r,1); if(!ans) puts("None"); else printf("%d\n",ans); } } return 0; }
岩手县北上市的「北上市立公园展胜地」,是陆奥国三大樱花名所之一。每年的四月中旬到五月初,这里都会举办盛大的祭奠。除了可以在盛开的樱花步道上乘坐观光马车徐行、还有横跨北上川上的鲤鱼旗,河畔还有当地特有的为祭奠祖先而编创的北上鬼剑舞。
假设,我们用一个包含 '(', ')'的括号字符串来区别每面鲤鱼旗的方向。一段括号序列被称为合法的,当且仅当满足两个条件:一、对于整个序列,左括号数量等于右括号;二、对于任意前缀,左括号的数目都不小于右括号的数目。岛娘想知道,对于一串括号字符串,有多少子串是合法的,你能帮助她么。
输入数据仅一行,包含一个长度为 n (1 ≤ n ≤ 106) 的括号字符串。
输出一行,表示合法的括号子串的数目。
(()())
4
首先,我们来整理一下如何求合法的子串数目
对于(()()(()))(),其实可以把各种括号进行分层
(( ) ( )(( ))) ( )
0 1 1 1 1 1 2 2 1 0 0 0
相同层的用等差数列求和就能算得当层的合法子串数
而需要特别处理的是多余的右括号,即没有左括号能与之匹配的右括号,对于这些右括号,统一分成-1组,不对其做处理即可
如:
) ) ) ) ( ( ) ( ) )
-1 -1 -1 -1 0 1 1 1 1 0
题目链接→1300 展胜地的鲤鱼旗
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-4 using namespace std; const int N = 1000005; const int M = 100000; const int inf = 100000; const int mod = 2009; char s[N]; stack<char> p; stack<int> m; int ans[N],q[N]; int main() { int i,k,c; while(~scanf("%s",s)) { c=k=0; while(!p.empty()) p.pop(); while(!m.empty()) m.pop(); for(i=0;s[i]!='\0';i++) if(s[i]=='(') { if(m.empty()) m.push(0); else m.push(m.top()+1); q[k++]=m.top(); p.push('('); } else { if(!p.empty()&&p.top()=='(') { q[k++]=m.top(); p.pop(); m.pop(); } else { p.push(')'); q[k++]=-1; } } /*for(i=0;i<k;i++) printf("%d ",q[i]); puts("");*/ memset(ans,0,sizeof(ans)); ans[q[0]]++; for(i=1;i<k;i++) { if(q[i]<q[i-1]) { if(q[i-1]!=-1) { ans[q[i-1]]/=2; c+=ans[q[i-1]]*(ans[q[i-1]]+1)/2; ans[q[i-1]]=0; } } ans[q[i]]++; //printf("%d %d\n",i,c); } if(q[i-1]!=-1) { ans[q[i-1]]/=2; c+=ans[q[i-1]]*(ans[q[i-1]]+1)/2; ans[q[i-1]]=0; //printf("#c=%d\n",c); } for(i=q[i-1]-1;i>=0;i--) { ans[i]/=2; c+=ans[i]*(ans[i]+1)/2; ans[i]=0; //printf("@c=%d\n",c); } printf("%d\n",c); } return 0; } /* ()()(())()) (())()))(((()))(() */
菜鸟成长记