- Turing Tree HDU - 3333
- Infinite Inversions CodeForces - 540E
(一次学会树状数组求逆序对巩固离散化)
模板:
vector<int> v;
int getid(int k)
{
return lower_bound(v.begin(),v.end(),k)-v.begin()+1;
}
for(int i=1;i<=N;i++){scanf("%d",&s[i]);
v.push_back(s[i]);}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
getid(s[p]);
Turing Tree HDU - 3333
http://acm.hdu.edu.cn/showproblem.php?pid=3333题解链接:https://blog.csdn.net/T__TSZ/article/details/77529140
题解我懒得打。这个题解可以的。由于这里重点在离散化所以下面的代码直接是从代码基础改的。用离散模板改的。实测比原答案快。
#include<iostream>
#include<algorithm>
#include <vector>
#include<cstdio>
#include<cstring>
using namespace std;
#define ls o<<1
#define rs o<<1|1
#define lson L,mid,ls
#define rson mid+1,R,rs
#define mdzz int mid=(L+R)>>1;
int N,M;
long long tree[120005];
int s[30005];
int hashs[30005];
int vis[30005];
long long ans[100003];
struct node
{
int l,r,t;
bool operator <(const node &a)const
{
return a.r>r;
}
}q[200003];
void pushup(int o){
tree[o]=tree[ls]+tree[rs];
}
void update(int p,int L,int R,int o,int v){ //点修改
if(L==R){
tree[o]+=v;
return;
}
mdzz;
if(p<=mid) update(p,lson,v);
else update(p,rson,v);
pushup(o);
}
long long query(int l,int r,int L,int R,int o){//[l,r]区间询问
if(r>=R&&l<=L) return tree[o];
mdzz;
long long ans=0;
if(l<=mid)
ans+=query(l,r,lson);
if(r>mid)
ans+=query(l,r,rson);
return ans;
}
vector<int> v;
int getid(int k)
{
return lower_bound(v.begin(),v.end(),k)-v.begin()+1;
}
int main()
{
int T;
scanf("%d",&T);
int a,b;
while(T--)
{
memset(vis,0,sizeof vis);
memset(tree,0,sizeof tree);
memset(hashs,0,sizeof hashs);
scanf("%d",&N);
for(int i=1;i<=N;i++){scanf("%d",&s[i]);
v.push_back(s[i]);}
scanf("%d",&M);
for(int i=1;i<=M;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].t=i;
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
sort(q+1,q+M+1);
int p=1;
for(int i=1;i<=M;i++)
{
while(p<=q[i].r)
{
int temp=getid(s[p]);
if(vis[temp])
update(vis[temp],1,N,1,-s[p]);
vis[temp]=p;
update(p,1,N,1,s[p]);
p++;
}
ans[q[i].t]=query(q[i].l,q[i].r,1,N,1);
}
for(int i=1;i<=M;i++)printf("%lld\n",ans[i]);
}
return 0;
}
Infinite Inversions CodeForces - 540E
离散化+树状数组树状数组入门:(简洁清楚)https://blog.csdn.net/Small_Orange_glory/article/details/81290634
嫌麻烦的看这里:sum函数求(1,x)的值得和。update更新x和与x有关的值。lowbit是树状数组特有的一个用来调节点的。(不想看原理的话知道这些就可以写这道题了)
题目来源:https://codeforces.com/problemset/problem/540/E
代码来源:https://blog.csdn.net/whai362/article/details/48827207
题解: 如何通过树状数组实现求逆序对。 把数字投到书里面,找比数大的有多少个就是当前逆序对(模拟一下)但是这里是无限序列,不能一个个投。
构造:要简单构造一下。如果强行构造整个数列(样例构造4132时会比较麻烦的,这里只是空了一个,如果给你两个操作交换12和10000 10001全构造就gg了)不太好,所以把交换的数放到pool里面,然后遇到断层,就添一个新的数进去记录中间有多少(具体看代码中循环1).这样就基本构造完了。
离散:然后离散化(用id)要投的全都准备好。
模拟:然后模拟交换。
寻找:最后从尾部开始往里面头找比自己小的(从头也可以就找比自己大呗就是麻烦了点,这里头尾指的是交换玩顺序)最后输出答案即可。
重点离散化看这里:
以下为未离散的代码(是不能a的,但是跟下面代码做比较可以清晰看出哪里是离散部分。一开始我以为pool是用来离散的,后面发现是题目本来需要的,这里只是用id进行了离散。不同点用注释!!!表示出来,不离散的的话,这个题可以写的更简单只是为了对比**所以第一个代码是在第二个改的)
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define P pair<int ,int>
#define PB push_back
#define X first
#define Y second
#define LL long long
const int N = 1e5 + 5;
vector<P> pool;
int pool_cnt;
int u[N], v[N];
int id[N * 4];
int num[N * 4];
int BIT[N * 4];
int lowbit(int x) { return x & -x; }
int sum(int x) {
int s = 0;
while (x > 0) {
s += BIT[x];
x -= lowbit(x);
}
return s;
}int maxx=-1;
void update(int x, int c) {
while (x <= maxx) {//!!!
BIT[x] += c;
x += lowbit(x);
}
}
int get_p(int x) {
return lower_bound(pool.begin(), pool.begin() + pool_cnt, P(x, 0)) - pool.begin() + 1;
}
int main() {
int n;
cin>>n;
for(int i = 0; i < n; ++i) {
cin>>u[i]>>v[i];
pool.PB(P(u[i], 1));
pool.PB(P(v[i], 1));
maxx=max(maxx,max(u[i],v[i]));
}
sort(pool.begin(), pool.end());
pool_cnt = unique(pool.begin(), pool.end()) - pool.begin();
for(int i = 0; i < pool_cnt - 1; ++i) {//循环1
int x = pool[i].X + 1;
if(x == pool[i + 1].X) continue;
int y = pool[i + 1].X - x;
pool.PB(P(x, y));
}
sort(pool.begin(), pool.end());
pool_cnt = unique(pool.begin(), pool.end()) - pool.begin();
for(int i = 0; i < pool_cnt; ++i) {
id[i + 1] = pool[i].X;//!!!
num[pool[i].X] = pool[i].Y;//!!!
}
for(int i = 0; i < n; ++i) {
u[i] = get_p(u[i]);
v[i] = get_p(v[i]);
swap(id[u[i]], id[v[i]]);
}
LL ans = 0;
for(int i = pool_cnt; i > 0; --i) {
LL tmp = sum(id[i]);
ans += tmp * num[id[i]];
// cout<<tmp<<id[i]<<num[id[i]]<<endl;
update(id[i], num[id[i]]);
}
cout<<ans<<endl;
return 0;
}
以下离散
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define P pair<int ,int>
#define PB push_back
#define X first
#define Y second
#define LL __int64
const int N = 1e5 + 5;
vector<P> pool;
int pool_cnt;
int u[N], v[N];
int id[N * 4];
int num[N * 4];
int BIT[N * 4];
int lowbit(int x) { return x & -x; }
int sum(int x) {
int s = 0;
while (x > 0) {
s += BIT[x];
x -= lowbit(x);
}
return s;
}
void update(int x, int c) {
while (x <= pool_cnt) {//!!!
BIT[x] += c;
x += lowbit(x);
}
}
int get_p(int x) {
return lower_bound(pool.begin(), pool.begin() + pool_cnt, P(x, 0)) - pool.begin() + 1;
}
int main() {
int n;
cin>>n;
for(int i = 0; i < n; ++i) {
cin>>u[i]>>v[i];
pool.PB(P(u[i], 1));
pool.PB(P(v[i], 1));
}
sort(pool.begin(), pool.end());
pool_cnt = unique(pool.begin(), pool.end()) - pool.begin();
for(int i = 0; i < pool_cnt - 1; ++i) {
int x = pool[i].X + 1;
if(x == pool[i + 1].X) continue;
int y = pool[i + 1].X - x;
pool.PB(P(x, y));
}
sort(pool.begin(), pool.end());
pool_cnt = unique(pool.begin(), pool.end()) - pool.begin();
for(int i = 0; i < pool_cnt; ++i) {
id[i + 1] = i + 1;//!!!
num[i + 1] = pool[i].Y;//!!!
}
for(int i = 0; i < n; ++i) {
u[i] = get_p(u[i]);
v[i] = get_p(v[i]);
swap(id[u[i]], id[v[i]]);
}
LL ans = 0;
for(int i = pool_cnt; i > 0; --i) {
LL tmp = sum(id[i]);
ans += tmp * num[id[i]];
update(id[i], num[id[i]]);
}
cout<<ans<<endl;
return 0;
}
我的AC代码(不用看了之前差不多。只是自己写了放在这里记录一下。)一开始下面求和开错了还有前面有个地方循环限制写错了,错了几发忧桑。
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
#define P pair<int ,int>
#define X first
#define Y second
typedef long long ll;
const int N = 1e5 + 5;
int BIT[N * 4];
int lowbit(int x) { return x & -x; }
int sum(int x) {
int s = 0;
while (x > 0) {
s += BIT[x];
x -= lowbit(x);
}
return s;
}
void update(int x, int c,int mx) {
while (x <= mx) {//!!!
BIT[x] += c;
x += lowbit(x);
}
}
vector<P> pool;
int length;
int u[N], v[N];
int id[N * 4];
int num[N * 4];
int get_p(int x) {
return lower_bound(pool.begin(), pool.begin() + length, P(x, 0)) - pool.begin();
}
int main()
{
int n;scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&u[i],&v[i]);
pool.push_back(P(u[i],1));
pool.push_back(P(v[i],1));
}
sort(pool.begin(),pool.end());
length = unique(pool.begin(), pool.end()) - pool.begin();
for(int i=0;i<length-1;i++){
if(pool[i].X+1==pool[i+1].X)continue;
int cishu=pool[i+1].X-pool[i].X-1;
pool.push_back(P(pool[i].X+1,cishu));
}
sort(pool.begin(),pool.end());
length = unique(pool.begin(), pool.end()) - pool.begin();
for(int i=0;i<length;i++){
id[i+1]=i+1;
num[i+1]=pool[i].Y;
// cout<<i+1<<pool[i].X<<pool[i].Y<<endl;
}
for(int i=0;i<n;i++){
int loca1=get_p(u[i])+1;
int loca2=get_p(v[i])+1;
swap(id[loca1],id[loca2]);
}
ll ans=0;
for(int i=length;i>0;i--){
ll temp=sum(id[i]);
ans+=temp*num[id[i]];
update(id[i],num[id[i]],length);
}
printf("%lld",ans);
}