把对妹子的烦躁,转移到码代码的身上,你妹谁知道它又转回来了。
Rotate |
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
Total Submission(s): 77 Accepted Submission(s): 17 |
Problem Description
Recently yifenfei face such a problem that give you millions of positive integers,tell how many pairs i and j that satisfy F[i] smaller than F[j] strictly when i is smaller than j strictly. i and j is the serial number in the interger sequence. Of course, the problem is not over, the initial interger sequence will change all the time. Changing format is like this [S E] (abs(E-S)<=1000) that mean between the S and E of the sequece will Rotate one times.
For example initial sequence is 1 2 3 4 5. If changing format is [1 3], than the sequence will be 1 3 4 2 5 because the first sequence is base from 0. |
Input
The input contains multiple test cases.
Each case first given a integer n standing the length of integer sequence (2<=n<=3000000) Second a line with n integers standing F[i](0<F[i]<=10000) Third a line with one integer m (m < 10000) Than m lines quiry, first give the type of quiry. A character C, if C is ‘R’ than give the changing format, if C equal to ‘Q’, just put the numbers of satisfy pairs. |
Output
Output just according to said.
|
Sample Input
5 1 2 3 4 5 3 Q R 1 3 Q |
Sample Output
10 8 |
标题要不要这么对应我的心情啊混蛋!
这题被坑了。看不懂树状数组的神奇用法就算了,居然还要开外挂才过。而且外挂要开三处……到底是有多少输入啊混蛋!难怪连建议用scanf都不写了,因为用scanf都没用啊泪!
#include <iostream>
#define maxn 10002
#define l __int64
using namespace std;
int n;
int c[maxn];
int ans[3000003];
int lowbit(int x)
{ return -x&x; }
void add(int pos)
{
while(pos<maxn)
{
c[pos]++;
pos+=lowbit(pos);
}
}
l sum(int pos)
{
l s=0;
while(pos>0)
{
s+=c[pos];
pos-=lowbit(pos);
}
return s;
}
bool scan_ud(int &num) { // 传说中的外挂
char in;
in = getchar();
/* if (in == EOF)
return false; */
while (in < '0' || in > '9') //leading spaces?
in = getchar();
num = in - '0';
while (in = getchar(), in >= '0' && in <= '9') {
num *= 10, num += in - '0';
}
return true;
}
int main()
{
int i;
int m;
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof(c));
l val=0;
for(i=0;i<n;i++)
{
//scanf("%d",&ans[i]);
scan_ud(ans[i]);
add(ans[i]);
val+=sum(ans[i]-1);
//c[i] save the number small or equal to i in i's branch
//val need to plus what is smaller(cant equal!)
//so,-1
}
scanf("%d",&m);
while(m--)
{
char str[3];
scanf("%s",str);
if(str[0]=='Q')
{
printf("%I64d\n",val);
}
else
{
int s,e;
//scanf("%d%d",&s,&e);
scan_ud(s);
scan_ud(e);
if(s>e)
{
s=s^e;
e=s^e;
s=s^e;
}
if(s!=e)
{
int v=ans[s];
int t1=0,t2=0;
for(i=s;i<e;i++)
{
ans[i]=ans[i+1];//rotate
if(v<ans[i+1])
{
t1++;
}
if(v>ans[i+1])
t2++;
}
ans[e]=v;
val=val-t1+t2;
}
}
}
}
return 0;
}
注意:
1.val要用long long(__int64)存,输出用%I64d。
2.首先将N个数的顺序数用树状数组求出来。就是每输入一个树就查询之前比他小的保存。然后添加这个数。
3.然后对于每次R操作,统计在[S+1,E]区间中比v[S]大的数和小的数的个数,将之前的顺序数 - 比它大的数 + 比它小的数,更新这个值。具体可手推一下,就是原来在第一个数后面比他大的(构成顺序对的)现在移到它前面不构成顺序对了,所以减掉。小的同理。
4.外挂。
bool scan_ud(int &num) { // 传说中的外挂
char in;
in = getchar();
/* if (in == EOF)
return false; */
while (in < '0' || in > '9') //leading spaces?
in = getchar();
num = in - '0';
while (in = getchar(), in >= '0' && in <= '9') {
num *= 10, num += in - '0';
}
return true;
}
相当于自己写一个int输入。就是读字符乘十累加。注意前导空格(?)的消去。因为我们知道一定会有读入的所以in==EOF可忽视,其实用void也可以吧……
that's all~
好像抽人啊抽人啊抽人啊混蛋!