慢慢补题路:
1001 Another Meaning
标程 KMP用的神乎其神,感觉掉的不行,但是没想到这题还可以用stl写,我也是醉了,只怪自己dp没学好,不过也算学到了另一种用法吧。
题意:
hehehehe
hehe
用模式串去匹配主串,模式串可能有两个意思,问主串最多有几个意思?
比如样例就是 3 个意思 hehehe” can have 3 meaings: “* he”, “he*”, “hehehe”.
先看一种stl
C++中substr函数的用法
#include<string>
#include<iostream>
using namespace std;
main()
{
string s("12345asdf");
string a=s.substr(0,5); //获得字符串s中 从第0位开始的长度为5的字符串//默认时的长度为从开始位置到尾
cout<<a<<endl;
}
输出结果为:
12345
尼玛,早说有这种用法啊,我曹,那这道题就很简单了。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define ll __int64
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
const int N = 100005;
const int MOD = 1000000007;
int T;
int n, m;
int dp[N];
string a,b;
int main() {
scanf("%d", &T);
int cas = 0;
while (T--) {
cin>>a>>b;
dp[0] = 1;
n=a.size();
m=b.size();
for (int i = 0; i < n; i++) {
if(i>0)
dp[i] = dp[i - 1];
/* 如果这一位可以匹配
即a[i-m]-a[m] 可以和 b串匹配
*/
string cnt;
if(i+1-m>=0)
cnt=a.substr(i+1-m,m);
int flag=cnt==b?1:0;
if (i+1-m>=0 && flag) {
if(i+1==m)
dp[i]=2;
else
dp[i] = (dp[i] + dp[i-m]) % MOD;
//这种可能出现i-m <0 即第一组匹配会出错
//我们特殊处理一下就行
}
}
printf("Case #%d: %d\n", ++cas, dp[n-1]);
}
return 0;
}
这个题 当时粗略看了看,队友就过了
题意:
求冒泡排序(题中给出),某一个数 最左位置和最右位置的 差值。 随便推推不难发现,在这个排序中,其实求的就是每个数 后面的 比它小的数有多少个?因为,后面存在一个比他小的,他就会右移动, 但是当这个数最终位置在起始位置右边的时候,他肯定不会向左移动,哪怕前面有很多比它大的数。
所以这题就是求 每个数 后面的 比它小的数有多少个?= 前面比它大的数有多少个
换句话说:就是让我们求逆序数;
当年随意看了看n方 的方法,今天又想了许久,竟没有想出如何logn 做出来。惭愧!QAQ
学习了一下,感觉真是妙,自己真是菜。
序列
3 5 4 8 2 6 9
大体思路为:新建一个数组,将数组中每个元素置0
0 0 0 0 0 0 0
取数列中最大的元素,将该元素所在位置置1
0 0 0 0 0 0 1
统计该位置前放置元素的个数,为0
接着放第二大元素8,将第四个位置置1
0 0 0 1 0 0 1
统计该位置前放置元素的个数,为0
继续放第三大元素6,将第六个位置置1
0 0 0 1 0 1 1
统计该位置前放置元素的个数,为1
…
…
这样直到把最小元素放完,累加每次放元素是该元素前边已放元素的个数,这样就算出总的逆序数来了,或者每个元素的逆序数对有多少
统计个数,线段树即可完成
**特别注意一下 线段树 push_up的位置究竟 放在那里!!!!
改了很久的,这个很容易疏忽,一定要注意!!!!!!切记切记**
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<bitset>
#define mem(a) memset(a,0,sizeof(a))
#define ll __int64
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
struct seg{
int l,r;
int v;
}st[100005<<2];
void build(int l,int r,int rt){
st[rt].v=0;
st[rt].l=l;
st[rt].r=r;
if(l==r){
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt*2);
build(mid+1,r,(rt<<1)+1);
}
void push_up(int rt){
st[rt].v=max(st[rt].v,st[rt*2].v+st[(rt*2)+1].v);
//应该取最大值,不取最大值,可能为0
}
void update(int p,int rt){
if(st[rt].l==p && st[rt].r==p){
st[rt].v=1;
return ;
}
int mid=(st[rt].l+st[rt].r)/2;
if(p<=mid){
update(p,rt*2);
}
else
update(p,(rt*2)+1);
push_up(rt); //连push_up的位置都不会放了??? 白学了!!!!
}
int qur(int l,int r,int rt){
if(st[rt].l==l &&st[rt].r==r){
return st[rt].v;
}
push_up(rt);
int mid=(st[rt].l+st[rt].r)>>1;
int ans=0;
if(mid>=r){
ans+=qur(l,r,rt<<1);
}
else if(l>mid){
ans+=qur(l,r,(rt<<1)+1);
}
else{
ans+=qur(l,mid,rt<<1);
ans+=qur(mid+1,r,(rt<<1)+1);
}
return ans;
}
int a[100005];
int pos[100005];
int f[100005];
int main(){
//freopen("1.txt","r",stdin);
int t;
scanf("%d",&t);
int cas=1;
while(t--){
printf("Case #%d:",cas++);
int n;
scanf("%d",&n);
build(1,n,1);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
for(int i=n;i>=1;i--){
int cnt=qur(1,pos[i],1); //i 前面比ai 大的
cnt=n-pos[i] -(n-i-cnt); // i后面比ai 小的
int left,righ;
left=min(pos[i],i);
righ=pos[i]+cnt;
f[i]=abs(left-righ);
update(pos[i],1);
}
for(int i=1;i<=n;i++){
printf(" %d",f[i]);
}
printf("\n");
}
return 0;
}