2014北邮新生归来赛解题报告d-e
D:
399. Who Is Joyful
题目描述
There are several little buddies standing in a line. We say someone is a joyful little buddy, if there exists a little buddy whose height is smaller than him in the front of him and there exists a little buddy whose height is bigger than him in the back of him. Now there are N little buddies, numbered from 1 to N. Their heights h are known. Give you two numbers A and B. Query that in the closed interval whose two ends are A and B, if the joyfulness of the little buddies in the interval have nothing to do with the little buddies out of the interval, how many little buddies are joyful in total in the interval.
输入格式
In the first line there is an integer T (T<=50), indicates the number of test cases. For each case, the first line contains one integer N (1<=N<=1e5). The second line contains N integers hi (1<=hi<=1e9, 1<=i<=N), indicate the heights of the little buddies from the beginning to the end. The third line contains an integer Q (1<=Q<=1e5), indicates the number of queries. And in the following Q lines, each line contains two integers A and B (1<=A, B<=N).
输出格式
For each case, output the case number as shown, and then print the answers to the queries, every query in a single line.
输入样例
2
6
5 2 3 1 4 5
1
2 5
8
1 4 5 5 1 1 3 2
2
3 6
1 3
输出样例
Case 1:
1
Case 2:
0
1
这里:
<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;"> while(j<ques[i].to){//后继节点满足条件//这是对的</span>
<span style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;"> j++; <span style="white-space:pre"> </span>//....</span>
<span style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;"> while(j<=ques[i].to){//后继节点满足条件//这是错的</span>
<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;"><span style="white-space:pre"> </span>//.......</span>
<span style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;"><span style="white-space:pre"> </span>j++;</span>原因是:不能加入区间from节点,要先得到区间内非to节点,然后+1得到后面那个点,这些才是当前可标示的点
#include <cstdio> #include <algorithm> #include <vector> #include <cstring> using namespace std; int n,m; #define MAXN 100011 int hi[MAXN]; int pre[MAXN]; int last[MAXN]; int sum[MAXN]; int heap[MAXN];//用于求解前驱节点/后继节点 vector<int > g[MAXN]; struct query{ int from,to,index; }; int ans[MAXN]; query ques[MAXN]; bool cmp(query q1, query q2){ return (q1.to<q2.to||(q1.to==q2.to&&q1.from<q2.from)); } int lowbit(int i){ return i&(-i); } void update(int a){//默认增量为1 // printf("update %d\n",a); if(a==0)return ; while(a<=n){ sum[a]++; a+=lowbit(a); } } int getSum(int i){ if(i==0)return 0; int ans2=0; while(i!=0){ ans2+=sum[i]; i-=lowbit(i); } return ans2; } int main(){ int ct; scanf("%d",&ct); for(int ci=1;ci<=ct;ci++){ memset(sum,0,sizeof(sum)); memset(pre,0,sizeof(pre)); memset(last,0,sizeof(last)); printf("Case %d:\n",ci); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",hi+i);//o(n) int heaplen=0;//用于记录堆栈深度 for(int i=1;i<=n;i++){//pre while(heaplen>0&&hi[heap[heaplen-1]]>=hi[i])heaplen--; if(heaplen>0) pre[i]=heap[heaplen-1];//o(cn) else pre[i]=0; heap[heaplen++]=i; } heaplen=0;//用于记录堆栈深度 for(int i=n;i>=1;i--){//last while(heaplen>0&&hi[heap[heaplen-1]]<=hi[i])heaplen--; if(heaplen>0) last[i]=heap[heaplen-1];//o(cn) else last[i]=0; heap[heaplen++]=i; } for(int i=0;i<=n;i++)g[i].clear(); for(int i=1;i<=n;i++){ g[last[i]].push_back(i);//对每个点u,筛选出所有比u小且在u前的数 } // for(int i=1;i<=n;i++){ // for(int k=0;k<g[i].size();k++){ // printf("g[%d][%d]:%d\n",i,k,g[i][k]); // } // } scanf("%d ",&m); for(int i=0;i<m;i++){ int a,b; scanf("%d %d",&a,&b);//深坑,a,b大小相对不一定 ques[i].from=min(a,b); ques[i].to=max(a,b); ques[i].index=i; } sort(ques,ques+m,cmp); // printf("Aftersort/n"); // for(int i=0;i<m;i++){ // printf("ques [%d]: from :%d to :%d index :%d\n",i,ques[i].from,ques[i].to,ques[i].index); // } // printf("\n"); for(int i=0, j=1;i<m&&j<=n;i++){ // printf("ques %d:\n",i); while(j<ques[i].to){//后继节点满足条件 j++; int len=g[j].size(); // printf("len g[%d]:%d\n",j,len); for(int k=0;k<len;k++){ // printf("pre g[%d][%d]:%d\n",j,k,pre[g[j][k]]); update(pre[g[j][k]]); } } // printf("getSum[quesfrom-1]:%d\n",getSum(ques[i].from-1)); // printf("getSum[questo]:%d\n",getSum(ques[i].to)); ans[ques[i].index]=getSum(ques[i].to)-getSum(ques[i].from-1); } for(int i=0;i<m;i++){ printf("%d\n",ans[i]); } } return 0; }
E:
400. 最小距离查询
题目描述
给定一个由小写字母a到z组成的字符串S,其中第i个字符为S[i](下标从0开始)。你需要完成下面两个操作: INSERT c 其中c是一个待输入的字符。你需要在字符串的末尾添加这个字符。保证输入的字符同样是a到z之间的一个小写字母。 QUERY x 其中x是一个输入的整数下标。对于这个询问,你需要回答在S当中和S[x]相等且与x最近的距离。输入保证x在当前字符串中合法。 例如S = "abcaba",如果我们操作: INSERT a 则在S的末端加一个字符a,S变成"abcabaa"。 接下来操作 QUERY 0 由于S[0] = a,在S中出现的离他最近的a在下标为3的位置上,距离为3 - 0 = 3。因此应当输出3。 接下来,如果 QUERY 4 S[4] = b,S中离它最近的b出现在下标为1处,距离为4 - 1 = 3。同样应当输出3。 给定初始字符串S和若干操作,对于每个QUERY,你需要求出相应的距离。
输入格式
输入的第一行是一个正整数
输出格式
对于每个QUERY,输出所求的最小距离。如果S中其它位置都不存在和它相同的字符,输出-1。
输入样例
2
axb
3
INSERT a
QUERY 0
QUERY 1
explore
3
INSERT r
QUERY 7
QUERY 1
输出样例
3
-1
2
-1
思路:就这么一不小心做出来了
/* USER_ID: test#xuesu PROBLEM: 400 SUBMISSION_TIME: 2014-07-12 15:08:38 */ #include <cstdio> #include <cstring> using namespace std; int c[26][100000]; int s[100000]; int len[100000]; int ps; int p[26]; void insertchar(char ch){ int pc=ch-'a'; s[ps]=pc; c[pc][p[pc]]=ps; len[ps]=p[pc]; p[pc]++; ps++; } int main(){ int t; scanf("%d",&t); while(t--){ char ch; ps=0; memset(p,0,sizeof(p)); while((ch=getchar())>'z'||ch<'a'){} insertchar(ch); while((ch=getchar())<='z'&&ch>='a'){ insertchar(ch); } char op[10]; int ct; scanf("%d",&ct); while(ct--){ scanf("%s",op); if(strcmp(op,"INSERT")==0){ while((ch=getchar())>'z'||(ch<'a')){} insertchar(ch); } else if(strcmp(op,"QUERY")==0){ int x; scanf("%d",&x); int pc=s[x]; if(p[pc]<=1)printf("-1\n"); else { int len1=0x3ffffff; int cc=len[x]; if(cc>0){ len1=x-c[pc][cc-1]; } if(cc<p[pc]-1&&c[pc][cc+1]-x<len1){ len1=c[pc][cc+1]-x; } printf("%d\n",len1); }} } } return 0; }
while(j<ques[i].to){//后继节点满足条件 j++;