单点更新 区间查询
坑点:cin cout 一直超时 改成 scanf 和printf 就过了

/*输入
t样例
N(N<=50000)
第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
输出
Case 1:
6
33
59
*/
#include <string.h>
#include <stdio.h>
using namespace std;
int n,t[50005];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)//单点更新
{
while(x<=n){
t[x]+=val;
x+=lowbit(x);//由叶子节点向上更新树状数组C,从左往右更新
}
}
int ask(int x)//求区间[1,i]内所有元素的和 即求前缀和
{
int ans=0;
while(x>0){
ans+=t[x];//从右往左累加求和
x-=lowbit(x);
}
return ans;
}
int main()
{
int tt,cnt=0,b,c,i,a;
char s[10];
scanf("%d",&tt);
while(tt--)
{
scanf("%d",&n);
memset(t,0,sizeof(t));
for(i=1;i<=n;i++)
{
scanf("%d",&a);
update(i,a);
}
printf("Case %d:\n",++cnt);
while(scanf("%s",s))
{
if(s[0]=='E') break;
scanf("%d%d",&c,&b);
if(s[0]=='S') update(c,-b);
if(s[0]=='A') update(c,b);
if(s[0]=='Q')
{
printf("%d\n",ask(b)-ask(c-1));
}
}
}
return 0;
}
这个题把数据离散化了 ,利用树状数组求数据的逆序对 ,即超快排的交换次数。

/*
在此问题中,您必须分析特定的排序算法。该算法通过交换两个相邻的序列元素,
直到该序列以升序排序,来处理n个不同整数的序列。对于输入序列
9 1 0 5 4,
Ultra-QuickSort产生输出
0 1 4 5 9。
您的任务是确定Ultra-QuickSort需要执行多少次交换操作才能对给定的输入序列进行排序。
输入项
输入包含几个测试用例。每个测试用例均以包含单个整数n <500,000(输入序列的长度)的一行开头。
接下来的n行中的每行都包含一个整数,即0≤a [i]≤999,999,999,即第i个输入序列元素。输入由长度为n = 0的序列终止。
不得处理此序列。
输出量
对于每个输入序列,程序将打印一行包含整数op的单行,op是对给定输入序列进行排序所需的最小交换操作数。
Input
5
9
1
0
5
4
3
1
2
3
0
Output
6
0
*/
#include <string.h>
#include <stdio.h>
#include <algorithm>
#define maxn 500010
using namespace std;
long long int n, a[maxn], b[maxn],t[maxn];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)//单点更新w
{
while(x<=n){
t[x]+=val;
x+=lowbit(x);//由叶子节点向上更新树状数组C,从左往右更新
}
}
long long int ask(int x)//求区间[1,i]内所有元素的和 即求前缀和
{
long long int ans=0;
while(x>0){
ans+=t[x];//从右往左累加求和
x-=lowbit(x);
}
return ans;
}
int main()
{
long long int ans=0;
//这里以下标1为序列的起点,一般情况下从0开始也可以
while(scanf("%lld",&n))
{
if(!n) break;
for(int i = 1;i <= n;i++)
{
scanf("%lld", &a[i]);
b[i] = a[i];//b是一个临时数组,用来得到离散化的映射关系
}
//下面使用了STL中的sort(排序),unique(去重),lower_bound(查找)函数
sort(b + 1, b + n + 1);//排序
int size = unique(b + 1, b + 1 + n) - b - 1;//去重,并获得去重后的长度size
for(int i = 1;i <= n;i++)
{
a[i] = lower_bound(b + 1, b + 1 + size, a[i]) - b;//通过二分查找,快速地把元素和映射对应起来
update(a[i],1);
ans +=(i-ask(a[i]));
}
printf("%lld\n",ans);
ans=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(t,0,sizeof(t));
}
return 0;
}
