【转】核心网络—BestCoder需要注意的几个问题

核心网络—BestCoder需要注意的几个问题.

1.不能随意hack,hack成功有加分,但是hack失败也会扣分!
2.不要随意提交已经AC的题目,罚时是这样的:最后一次AC的之前所有提交(无论AC与否)均算作罚时!其中AC的标为Accepted(Past),被hack掉的AC也会标为Accepted(Past)。
3.AC不代表真正的AC,比赛最后阶段有hack数据,如果被hack掉就不算AC。hack数据一般都是非常变态的输入,或者是大数据!有时候有些人刻意利用题目bug构造变态的数据导致全场无人AC……
4.hack时只能读别人的代码,无法复制,这是锻炼读代码的能力。
5.如果有一场比赛注册了,但是忘做了,只要没有该场比赛的提交记录就不会使Rating降低。
6.只有本场比赛进入前300才能使Rating升高,否则就降低。
7.ABCD四道题的难度是依次升高的,分数也是依次升高的,根据错的次数和AC时间而使所得分数不同。
8.比赛题目是民间的ACMer出的,如果发现题目中有大量的英语语法错误,请不要见怪。
9.比赛日期并非固定在周五或者周六或者周日,根据杭电oj的具体日程安排而定。比如,如果有网络赛,可能就要提前或者延后了。
10.最后你的很多AC的题目可能都会被hack掉,请不要见怪。
11.

以上错误我几乎都犯过……
O__O”…

【Bestcoder

1001 - Rikka with string

Accepts: 395
Submissions: 2281
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description

As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

One day, Yuta got a string which contains n letters but Rikka lost it in accident. Now they want to recover the string. Yuta remembers that the string only contains lowercase letters and it is not a palindrome string. Unfortunately he cannot remember some letters. Can you help him recover the string?

It is too difficult for Rikka. Can you help her?
Input

This problem has multi test cases (no more than 20). For each test case, The first line contains a number n(1≤n≤1000). The next line contains an n-length string which only contains lowercase letters and ‘?’ – the place which Yuta is not sure.
Output

For each test cases print a n-length string – the string you come up with. In the case where more than one string exists, print the lexicographically first one. In the case where no such string exists, output “QwQ”.
Sample Input

5
a?bb?
3
aaa

Sample Output

aabba
QwQ

WA得智商都被拉低了 QAQ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int dfs(int step,bool &state)//1:to check
{
int res;
if (step<m-1) res=dfs(step+1,state);
int pos=n-vec[step]-1;
cout<<step<<' '<<str[vec[step]]<<' '<<str[pos]<<endl;
for(char ch='a';ch<='z';ch++)
if (state&&str[pos]==ch)
{
if (ch<'z') continue;
else return -1;//error
}
else
{
str[vec[step]]=ch;
if (state&&str[pos]!='?'&&ch!=str[pos]) state=0;
if (ch!=str[pos]) return 1;
}
return -1;
}

AC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define CLEAR(a) memset((a),0,sizeof((a)))

using namespace std;

typedef long long LL;
const double pi = acos(-1.0);
const int maxn=2e3;
const int inf=99999999;
const float eps=1e-3;

vector<int> vec;
int n,m;
char s[maxn],str[maxn];

int dfs(int step,bool &state)//1:to check
{

int pos=n-vec[step]-1;
for(char ch='a';ch<='z';ch++)
{
str[vec[step]]=ch;
if (str[pos]!='?'&&ch!=str[pos]) {state=0;}
if (step<m-1) dfs(step+1,state);
if (state&&str[pos]!='?'&&ch!=str[pos]||!state) return 1;
}

return -1;
}

int main()
{

while(~scanf("%d",&n))
{
vec.clear();
scanf("%s",s);
memcpy(str,s,sizeof(s));
for(int i=0;i<n;i++)
if (s[i]=='?')
vec.push_back(i);
m=vec.size();
bool tmp=1;

if (m>1||m==1&&!(n%2&&vec[0]==n/2))
{
if (dfs(0,tmp)>=0) puts(str);
else puts("QwQ");
}
else
{
bool ans=1;
for(int i=1;i<=strlen(s)/2;i++)
if (s[i-1]!=s[strlen(s)-i])
{
ans=0;break;
}
if (m==1&&n%2&&vec[0]==n/2) str[vec[0]]='a';
puts(ans?"QwQ":str);
}

}
return 0;
}

[心痛]线段树或树状数组求逆序数

原文地址

线段树或树状数组求逆序数

求逆序数的方法有分治,归并,本文只介绍线段树或树状数组求逆序数的办法,众所周知,线段树和树状树可以用来解决区间操作问题,就是因为这两个算法区间操作的时间复杂度很低O(logN),才让这种方法具有可行性。

首先先来看一个序列   6 1 2 7 3 4 8 5,此序列的逆序数为5+3+1=9。冒泡法可以直接枚举出逆序数,但是时间复杂度太高O(n^2)。冒泡排序的原理是枚举每一个数组,然后找出这个数后面有多少个数是小于这个数的,小于它逆序数+1。仔细想一下,如果我们不用枚举这个数后面的所有数,而是直接得到小于这个数的个数,那么效率将会大大提高。

总共有N个数,如何判断第i+1个数到最后一个数之间有多少个数小于第i个数呢?不妨假设有一个区间 [1,N],只需要判断区间[i+1,N]之间有多少个数小于第i个数。如果我们把总区间初始化为0,然后把第i个数之前出现过的数都在相应的区间把它的值定为1,那么问题就转换成了[i+1,N]值的总和。再仔细想一下,区间[1,i]的值+区间[i+1,N]的值=区间[1,N]的值(i已经标记为1),所以区间[i+1,N]值的总和等于N-[1,i]的值!因为总共有N个数,不是比它小就是比它(大或等于)。

现在问题已经转化成了区间问题,枚举每个数,然后查询这个数前面的区间值的总和, i-[1,i] 既为逆序数。

线段树预处理时间复杂度O(NlogN),N次查询和N次插入的时间复杂度都为O(NlogN),总的时间复杂度O(3*NlogN)

树状数组不用预处理,N次查询和N次插入的时间复杂度都为O(NlogN),总的时间复杂度O(2*NlogN)

线段树:
&nbsp;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 线段树
#include <stdio .h>
#include <string .h>
#include <stdlib .h>
#define MAX 51000
#define MID(a,b) (a+b)>>1
#define R(a) (a< <1|1)
#define L(a) a<<1
typedef struct {
int num,left,right;
}Node;
int ans[MAX];
Node Tree[MAX<<2];
int n;

void Build(int t,int l,int r) //以1为根节点建立线段树
{
int mid;
Tree[t].left=l,Tree[t].right=r;
if(Tree[t].left==Tree[t].right)
{
Tree[t].num=0;
return ;
}
mid=MID(Tree[t].left,Tree[t].right);
Build(L(t),l,mid);
Build(R(t),mid+1,r);
}

void Insert(int t,int l,int r,int x) //向以1为根节点的区间[l,r]插入数字1
{
int mid;
if(Tree[t].left==l&&Tree[t].right==r)
{
Tree[t].num+=x;
return ;
}
mid=MID(Tree[t].left,Tree[t].right);
if(l>mid)
{
Insert(R(t),l,r,x);
}
else if(r< =mid)
{
Insert(L(t),l,r,x);
}
else
{
Insert(L(t),l,mid,x);
Insert(R(t),mid+1,r,x);
}
Tree[t].num=Tree[L(t)].num+Tree[R(t)].num;
}

int Query(int t,int l,int r) //查询以1为根节点,区间[l,r]的和
{
int mid;
if(Tree[t].left==l&&Tree[t].right==r)
return Tree[t].num;
mid=MID(Tree[t].left,Tree[t].right);
if(l>mid)
{
return Query(R(t),l,r);
}
else if(r<=mid)
{
return Query(L(t),l,r);
}
else
{
return Query(L(t),l,mid)+Query(R(t),mid+1,r);
}
}


int main()
{
int a,n,i,t;
scanf("%d",&t);
long long int k;
while(t--)
{
scanf("%d",&n);
memset(Tree,0,sizeof(Tree)); //初始化线段树
Build(1,1,n);
for(i=1;i<=n;i++) //输入n个数
{
scanf("%d",&ans[i]);
}
for(i=1,k=0;i<=n;i++)
{
a=ans[i];
Insert(1,a,a,1); //把线段树[ans[i],ans[i]]区间的值插入为1
k=k+(i-Query(1,1,a)); //查询区间[1,ans[i]]值的总和,逆序数等于i-[1,ans[i]]
}
printf("%lld\n",k);
}
return 0;
}

树状数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 树状数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAX 100010
int c[MAX],a[MAX],ans[MAX],n;

int Lowbit(int x) //返回二进制最后一个1所表示的数
{
return x&(-x);
}

void Updata(int x) //向前更新
{
while(x<=n)
{
c[x]++;
x+=Lowbit(x);
}
}

int Sum(int x) //向后更新求和
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=Lowbit(x);
}
return sum;
}

int main()
{
int i,t,k;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&ans[i]);
}
memset(c,0,sizeof(c)); //初始化树状数组
for(i=1,k=0;i<=n;i++)
{
Updata(ans[i]); //向后更新节点ans[i].k
k=k+(i-Sum(ans[i])); //向前查询节点ans[i].k
}
printf("%d\n",k);
}
return 0;
}

&nbsp;

FFZU-ACM月赛不行了

线段树/树状数组的另一种用法不会,它的逆向问题更不会

Mac OS 下怎样写作业

我本以为 存在WPS office for Mac而不存在Microsoft office for Mac,真实情况正好相反...