2018.3.9

打了一场cf….菜的抠脚

http://blog.csdn.net/a1035719430/article/details/79502382

昨天学的cdq分治。在很多偏序问题cdq分治都可以起到很好的效果(代替高级数据结构)
cdq—>
1、入门题:[cdq分治二维偏序]炉石传说
背景
自从掉入了炉石坑之后,mzx天天在想着自己的卡组收藏,终于有一天,他想到一个问题:我的卡组里面的随从质量都是些什么级别的?于是,他决定编程解决一下这个问题。

题目描述
mzx的卡组收藏中一共有n张随从牌,为了准确的描述这个问题,mzx定义一个随从的身材被另一个随从“完爆”当且仅当该随从的的攻击力和血量都不大于另一个随从,现在,mzx想求出每个随从能够“完爆”的其他随从数。注意,因为mzx是个分卡狂魔,所以他的卡组收藏中不存在两张身材相同的随从牌。

输入格式
输入数据第一行为一个正整数n。

接下来n行,第i+1行两个整数,分别表示第i个随从的攻击力和生命值。输入数据保证不存在两个随从的攻击力和生命值完全相同。

输出格式
输出文件一共i行,第i行表示第i个随从能够完爆的其他随从数。

input

5
1 1
5 1
7 1
3 3
5 5
output

0
1
2
1
3
数据规模与约定
n≤200000,0≤ai,bi≤1000000000.

注意并不只是数据量加强了。

题面数据生成:闵梓轩

时间限制:1s

空间限制:256MB

#include<bits/stdc++.h>
using namespace std;
int n,ans[201000];
struct point{
    int a,b,id;
}a[201000];
int read() { 
    bool flag = true; int num = 0;char c = getchar(); 
    for(;c < '0' || c > '9';c = getchar())if(c == '-') flag = false; 
    for(;c >= '0' && c <= '9';c = getchar()) num = ( num << 3 ) + ( num << 1 ) + c - 48; 
    if(flag) return num;  else return -num; 
}
bool mycup( point x,point y ){return x.a<y.a||(x.a==y.a&&x.b<y.b);}
void init(){
    n = read();
    for(int i = 1;i <= n;++i) a[i].a = read(),a[i].b = read(),a[i].id = i;
    sort(a + 1,a + n +1,mycup);
    return;
}
point tmp[201000];
void cdq(int l,int r){
    if(l  == r) return;
    int m = (l + r) / 2;
    cdq(l,m);cdq(m+1,r);
    int p = l,q = m + 1,t = 0;
    int sum=0;
    while( p <= m && q <= r)
     if(a[p].b <= a[q].b) sum++ ,tmp[++t] = a[p++];
      else ans[a[q].id] += sum , tmp[++t] = a[q++];
    while(p <= m) tmp[++t] = a[p++];
    while(q <= r) ans[a[q].id] += sum , tmp[++t] = a[q++];
    for(int i = 1;i <= t;++i) a[l+i-1] = tmp[i]; 
    return;
}
void print(){
    for(int i = 1;i <= n;++i)
     printf("%d\n",ans[i]);
    return;
}
int main(){
    init();
    cdq(1,n);
    print();
    return 0;
}

2、

[cdq分治二维偏序]数列求和

本题作为分治的练习题,当然可以用其他模板水过,希望珍惜练习的机会

题目描述
假设有一列数 {Ai }(1 ≤ i ≤ n) ,支持如下两种操作:

(1)将 A k 的值加 D 。( k, D 是输入的数)

(2) 输出 A s +A s+1 +…+A t 。( s, t 都是输入的数, S ≤ T )

根据操作要求进行正确操作并输出结果。

输入格式
输入文件第一行一个整数 n(0<=n<=100000) ;

第二行为 n 个整数,表示 {A i } 的初始值。

第三行为一个整数 m(0<=m<=150000) ,表示操作数。 下接 m 行,每行描述一个操作,有如下两种情况:

ADD k d ( 表示将 A k 加 d , 1<=k<=n , d 为整数 )

SUM s t (表示输出 A s +…+A t )

输出格式
对于每一个 SUM 提问,输出结果

样例数据
input

4
1 4 2 3
3
SUM 1 3
ADD 2 50
SUM 2 3
output

7
56
数据规模与约定
时间限制:1s1s
空间限制:256MB

#include<bits/stdc++.h>
using namespace std;
int n,t_q,aid,m;
int ans[151000];
struct queryy{
    int pl,kind,v;
}query[501000];
int read() { 
    bool flag = true; int num = 0;char c = getchar(); 
    for(;c < '0' || c > '9';c = getchar())if(c == '-') flag = false; 
    for(;c >= '0' && c <= '9';c = getchar()) num = ( num << 3 ) + ( num << 1 ) + c - 48; 
    if(flag) return num;  else return -num; 
}
bool check( int a, int b ){
    if(query[a].pl != query[b].pl) return query[a].pl < query[b].pl;
     else return query[a].kind==1;
}
void init(){
    n = read();
    for(int i = 1;i <= n;++i){
        int x = read();
        query[++t_q].pl = i;
        query[t_q].v = x;
        query[t_q].kind = 1;
    }
    m = read();
    for(int i = 1;i <= m;++i){
        char c=0;
        while(c != 'S' && c != 'A') c = getchar();
        if(c == 'A'){
           int x = read(),xx=read();
           query[++t_q].pl = x;
           query[t_q].v = xx ;
           query[t_q].kind = 1;
        } 
        else{
           int l=read(),r=read();
           query[++t_q].pl = l-1;
           query[t_q].v = ++aid;
           query[t_q].kind = 2;
           query[++t_q].pl = r;
           query[t_q].v = aid;
           query[t_q].kind = 3;
        }
    }
}
queryy tmp[501000];
void cdq(int l,int r){
    if(l == r) return;
    int m = (l + r)/2;
    cdq( l , m );cdq( m+1 , r );
    int p = l,q = m+1;
    int sum = 0,t=0;
    while( p <= m && q <= r ){
        if( check(p,q) ){
            if(query[p].kind == 1) sum += query[p].v;
            tmp[++t] = query[p++]; 
        }
        else{
            if(query[q].kind == 2) ans[ query[q].v ] -= sum;
            if(query[q].kind == 3) ans[ query[q].v ] += sum; 
            tmp[++t] = query[q++];
        }
    }
    while( p <= m ) tmp[++t] = query[p++];
    while( q <= r ) {
          if(query[q].kind == 2) ans[query[q].v] -= sum;    
          if(query[q].kind == 3) ans[query[q].v] += sum;
          tmp[++t] = query[q++];
    }
    for(int i = 1;i <= t;++i) query[l+i-1]=tmp[i];
    return;
}
void print(){
    for(int i = 1;i <= aid;++i) printf("%d\n",ans[i]);
    return;
}
int main(){
    init();
    cdq(1,t_q);
    print();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1035719430/article/details/79502412