kuangbin线段树专题(有的没用线段树,在之后会更新)

A - 敌兵布阵

C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。 
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的. 

Input

第一行一个整数T,表示有T组数据。 
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第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 表示结束,这条命令在每组数据最后出现; 
每组数据最多有40000条命令 

Output

对第i组数据,首先输出“Case i:”和回车, 
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。 

Sample Input

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 

Sample Output

Case 1:
6
33
59

//Full of love and hope for life

/*                                                            *               ******
 ***** *****                                                **             *******
 ********* *********                                      ***                 ******
 ************* *************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

struct node
{
    int data;
};

node tree[400010];

void creat(int root,int l,int r)//建树
{
    if(l==r)
    {
        cin >> tree[root].data;
        return ;
    }
    int mid=(l+r)/2;
    creat(2*root,l,mid);
    creat(2*root+1,mid+1,r);
    tree[root].data=tree[2*root].data+tree[2*root+1].data;
}

void updata1(int p,int v,int l,int r,int root)//更新加法
{
    int mid=(l+r)/2;
    if(l==r)
    {
        tree[root].data+=v;
        return ;
    }
    if(mid>=p)
    {
        updata1(p,v,l,mid,2*root);
    }
    else
    {
        updata1(p,v,mid+1,r,2*root+1);
    }
    tree[root].data=tree[2*root].data+tree[2*root+1].data;
}

void updata2(int p,int v,int l,int r,int root)//更新减法
{
    int mid=(l+r)/2;
    if(l==r)
    {
        tree[root].data-=v;
        return ;
    }
    if(mid>=p)
    {
        updata2(p,v,l,mid,2*root);
    }
    else
    {
        updata2(p,v,mid+1,r,2*root+1);
    }
    tree[root].data=tree[2*root].data+tree[2*root+1].data;
}

int sum(int i,int j,int l,int r,int root)//求和
{
    int ans=0;
    if(i<=l&&j>=r)
    {
        return tree[root].data;
    }
    int mid=(l+r)/2;
    if(i<=mid)
    {
        ans+=sum(i,j,l,mid,2*root);
    }
    if(j>mid)
    {
        ans+=sum(i,j,mid+1,r,2*root+1);
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    int a,b,x,y,k=0;
    char s[10];
    cin >> a;
    while(a--)
    {
        k++;
        cin >> b;
        creat(1,1,b);
        cout << "Case " << k << ":" << endl;
        while(cin >> s)
        {
            if(strcmp(s,"Query")==0)
            {
                cin >> x >> y;
                cout << sum(x,y,1,b,1) << endl;;
            }
            if(strcmp(s,"Add")==0)
            {
                cin >> x >> y;
                updata1(x,y,1,b,1);
            }
            if(strcmp(s,"Sub")==0)
            {
                cin >> x >> y;
                updata2(x,y,1,b,1);
            }
            if(strcmp(s,"End")==0)
            {
                break;
            }
        }
    }
    return 0;
}

B - I Hate It

 


//Full of love and hope for life
/*
                                                            *               ******
      ******** ********                                     **             *******
   *********** ***********                                ***                 ******
 ************* *************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <algorithm>
#include <stdio.h>
#define lt 2*n
#define rt 2*n+1

using namespace std;

struct node
{
    int ma;
};

node tree[800000];

void creat(int l,int r,int t)
{
    if(l==r)
    {
        cin >> tree[t].ma;
        return ;
    }
    int mid=(l+r)/2;
    creat(l,mid,2*t);
    creat(mid+1,r,2*t+1);
    tree[t].ma=max(tree[2*t].ma,tree[2*t+1].ma);
}

void updata(int p,int v,int l,int r,int t)
{
    if(l==r)
    {
        tree[t].ma=v;
        return ;
    }
    int mid=(l+r)/2;
    if(p<=mid)
    {
        updata(p,v,l,mid,2*t);
    }
    else
    {
        updata(p,v,mid+1,r,2*t+1);
    }
    tree[t].ma=max(tree[2*t].ma,tree[2*t+1].ma);
}

int query(int L,int R,int l,int r,int t)
{
    if(L<=l&&R>=r)
    {
        return tree[t].ma;
    }
    int mid=(l+r)/2;
    int ans1=0,ans2=0;
    if(L<=mid)
    {
        ans1=query(L,R,l,mid,2*t);
    }
    if(R>mid)
    {
        ans2=query(L,R,mid+1,r,2*t+1);
    }
    return max(ans1,ans2);
}

int main()
{
    ios::sync_with_stdio(false);
    int a,b,x,y;
    char s;
    while(cin >> a >> b)
    {
        creat(1,a,1);
        while(b--)
        {
            cin >> s;
            cin >> x >> y;
            if(s=='Q')
            {
                cout << query(x,y,1,a,1) << endl;
            }
            if(s=='U')
            {
                updata(x,y,1,a,1);
            }
        }
    }
    return 0;
}

C - A Simple Problem with Integers

 

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.


//Full of love and hope for life
/*
                                                            *               ******
      ******** ********                                     **             *******
   *********** ***********                                ***                 ******
 ************* *************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <algorithm>
#include <stdio.h>

using namespace std;

typedef long long ll;
const int N = 2000010;

struct node
{
    int l,r;
    ll sum,lazy;
};

node tree[4*N];

void pushdown(int t)
{
    tree[2*t].sum+=tree[t].lazy*(tree[2*t].r-tree[2*t].l+1);
    tree[2*t+1].sum+=tree[t].lazy*(tree[2*t+1].r-tree[2*t+1].l+1);
    tree[2*t].lazy+=tree[t].lazy;
    tree[2*t+1].lazy+=tree[t].lazy;
    tree[t].lazy=0;
}

void creat(int l,int r,int t)
{
    tree[t].l=l;
    tree[t].r=r;
    tree[t].lazy=0;
    if(l==r)
    {
        scanf("%lld",&tree[t].sum);
        return ;
    }
    int mid=(l+r)/2;
    creat(l,mid,2*t);
    creat(mid+1,r,2*t+1);
    tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;
}

void updata(int l,int r,int v,int t)
{
    int i=tree[t].l;
    int j=tree[t].r;
    if(l==i&&j==r)
    {
        tree[t].sum+=(j-i+1)*v;
        tree[t].lazy+=v;
        return ;
    }
    if(tree[t].lazy)
    {
        pushdown(t);
    }
    int mid=(i+j)/2;
    if(mid>=r)
    {
        updata(l,r,v,2*t);
    }
    else if(mid<l)
    {
        updata(l,r,v,2*t+1);
    }
    else
    {
        updata(l,mid,v,2*t);
        updata(mid+1,r,v,2*t+1);
    }
    tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;
}

ll query(int l,int r,int t)
{
    int i=tree[t].l;
    int j=tree[t].r;
    if(tree[t].lazy)
    {
        pushdown(t);
    }
    if(l<=i&&r>=j)
    {
        return tree[t].sum;
    }
    int mid=(i+j)/2;
    if(mid>=r)
    {
        return query(l,r,2*t);
    }
    else if(mid<l)
    {
        return query(l,r,2*t+1);
    }
    else
    {
        return query(l,mid,2*t)+query(mid+1,r,2*t+1);
    }
}

int main()
{
    int a,b,x,y,v;
    char s;
    scanf("%d%d",&a,&b);
    creat(1,a,1);
    getchar();
    while(b--)
    {
        scanf("%c",&s);
        if(s=='Q')
        {
            scanf("%d%d",&x,&y);
            printf("%lld\n",query(x,y,1));
        }
        if(s=='C')
        {
            scanf("%d%d%d",&x,&y,&v);
            updata(x,y,v,1);
        }
        getchar();
    }
    return 0;
}

E - Just a Hook

 

In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length. 



Now Pudge wants to do some operations on the hook. 

Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks. 
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows: 

For each cupreous stick, the value is 1. 
For each silver stick, the value is 2. 
For each golden stick, the value is 3. 

Pudge wants to know the total value of the hook after performing the operations. 
You may consider the original hook is made up of cupreous sticks. 

Input

The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases. 
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations. 
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind. 

Output

For each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example. 

Sample Input

1
10
2
1 5 2
5 9 3

Sample Output

Case 1: The total value of the hook is 24.

//Full of love and hope for life
/*
                                                            *               ******
      ******** ********                                     **             *******
   *********** ***********                                ***                 ******
 ************* *************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <algorithm>
#include <stdio.h>
#define lt 2*n
#define rt 2*n+1
#define inf 0x3f3f3f3f;

using namespace std;

typedef long long ll;

struct node
{
    ll sum,lazy;
    int l,r;
};

node tree[400000];

void pushdown(int t)
{
    tree[2*t].sum=tree[t].lazy*(tree[2*t].r-tree[2*t].l+1);
    tree[2*t+1].sum=tree[t].lazy*(tree[2*t+1].r-tree[2*t+1].l+1);
    tree[2*t].lazy=tree[t].lazy;
    tree[2*t+1].lazy=tree[t].lazy;
    tree[t].lazy=0;
}

void creat(int l,int r,int t)
{
    tree[t].l=l;
    tree[t].r=r;
    tree[t].lazy=0;
    if(l==r)
    {
        tree[t].sum=1;
        return ;
    }
    int mid=(l+r)/2;
    creat(l,mid,2*t);
    creat(mid+1,r,2*t+1);
    tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;
}

void updata(int l,int r,int x,int t)
{
    int i=tree[t].l;
    int j=tree[t].r;
    if(i==l&&r==j)
    {
        tree[t].sum=(j-i+1)*x;
        tree[t].lazy=x;
        return ;
    }
    if(tree[t].lazy)
    {
        pushdown(t);
    }
    int mid=(i+j)/2;
    if(r<=mid)
    {
        updata(l,r,x,2*t);
    }
    else if(mid<l)
    {
        updata(l,r,x,2*t+1);
    }
    else
    {
        updata(l,mid,x,2*t);
        updata(mid+1,r,x,2*t+1);
    }
    tree[t].sum=tree[2*t].sum+tree[2*t+1].sum;
}

ll query(int l,int r,int t)
{
    int i=tree[t].l;
    int j=tree[t].r;
    if(tree[t].lazy)
    {
        pushdown(t);
    }
    if(i>=l&&r<=j)
    {
        return tree[t].sum;
    }
    int mid=(i+j)/2;
    if(r<=mid)
    {
        return query(l,r,2*t);
    }
    else if(mid<l)
    {
        return query(l,r,2*t+1);
    }
    else
    {
        return query(l,mid,2*t)+query(mid+1,r,2*t+1);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int a,b,c,x,y,z,k=0;
    cin >> a;
    while(a--)
    {
        k++;
        cin >> b;
        creat(1,b,1);
        cin >> c;
        while(c--)
        {
            cin >> x >> y >> z;
            updata(x,y,z,1);
        }
        cout << "Case " << k << ": The total value of the hook is " << query(1,a,1) << "." << endl;
    }
    return 0;
}

 

F - Count the Colors(没用线段树,暴力做的)

Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you can see at last.

 

Input



The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

 

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.

 

Output



Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

 

If some color can't be seen, you shouldn't print it.

Print a blank line after every dataset.

 

Sample Input



5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1

 

 

Sample Output



1 1
2 1
3 1

 

1 1

0 2
1 1


//Full of love and hope for life

/*                                                            *               ******
 ***** *****                                                **             *******
 ********* *********                                      ***                 ******
 ************* *************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

int main()
{
    int a,i,x,y,z,t,g,h,k,j;
    int n[8010],m[8010];
    while(cin >> a)
    {
        t=0;
        g=10000;
        h=0;
        k=10000;
        memset(n,-1,sizeof(n));
        memset(m,0,sizeof(m));
        for(i=1; i<=a; i++)
        {
            cin >> x >> y >> z;
            if(y>t)
            {
                t=y-1;
            }
            if(x<g)
            {
                g=x;
            }
            for(j=x; j<y; j++)
            {
                n[j]=z;
            }
        }
        n[t+1]=10000;
        for(i=g; i<=t; i++)
        {
            if(n[i]!=-1)
            {
                if(n[i]!=n[i+1])
                {
                    m[n[i]]++;
                }
                if(h<n[i])
                {
                    h=n[i];
                }
                if(k>n[i])
                {
                    k=n[i];
                }
            }
        }
        for(i=k; i<=h; i++)
        {
            if(m[i]!=0)
            {
                cout << i << " " << m[i] << endl;
            }
        }
        cout << endl;
    }
    return 0;
}

 

J - Assign the task(没用线段树,用的并查集)

 

There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordinates are your subordinates as well. If you are nobody's boss, then you have no subordinates,the employee who has no immediate boss is the leader of whole company.So it means the N employees form a tree. 

The company usually assigns some tasks to some employees to finish.When a task is assigned to someone,He/She will assigned it to all his/her subordinates.In other words,the person and all his/her subordinates received a task in the same time. Furthermore,whenever a employee received a task,he/she will stop the current task(if he/she has) and start the new one. 

Write a program that will help in figuring out some employee’s current task after the company assign some tasks to some employee.

Input

The first line contains a single positive integer T( T <= 10 ), indicates the number of test cases. 

For each test case: 

The first line contains an integer N (N ≤ 50,000) , which is the number of the employees. 

The following N - 1 lines each contain two integers u and v, which means the employee v is the immediate boss of employee u(1<=u,v<=N). 

The next line contains an integer M (M ≤ 50,000). 

The following M lines each contain a message which is either 

"C x" which means an inquiry for the current task of employee x 

or 

"T x y"which means the company assign task y to employee x. 

(1<=x<=N,0<=y<=10^9)

Output

For each test case, print the test case number (beginning with 1) in the first line and then for every inquiry, output the correspond answer per line.

Sample Input

1 
5 
4 3 
3 2 
1 3 
5 2 
5 
C 3 
T 2 1
 C 3 
T 3 2 
C 3

Sample Output

Case #1:
-1 
1 
2

//Full of love and hope for life

/*                                                            *               ******
 ***** *****                                                **             *******
 ********* *********                                      ***                 ******
 ************* *************                    **      ****
*****************************                         *****
*****************************                       ******
*****************************                     *******            *********
 ***************************                 ***********           *********             **********
   ***********************                        *******            *********
     *******************                            ******
       ***************                                *****
         ***********                            **      ****
           *******                                        ***                 ******
             ***                                            **             *******
              *                                               *               ******
*/

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <map>

using namespace std;

struct node
{
    int num,x;
};

node n[50010];
int f[50010];

int main( )
{
    int a,b,x,y,ans,k=0;
    char s;
    cin >> a;
    while(a--)
    {
        k++;
        cin >> b;
        memset(f,-1,sizeof(f));
        memset(n,-1,sizeof(n));
        for(int i=1; i<b; i++)
        {
            cin >> x >> y;
            f[x]=y;
        }
        cin >> b;
        ans=0;
        cout << "Case #" << k << ":" << endl;
        while(b--)
        {
            cin >> s;
            if(s=='T')
            {
                cin >> x >> y;
                n[x].x=y;
                n[x].num=ans++;
            }
            if(s=='C')
            {
                cin >> x;
                int g,h;
                g=n[x].x;
                h=n[x].num;
                x=f[x];
                while(x!=-1)
                {
                    if(n[x].num>h)
                    {
                        h=n[x].num;
                        g=n[x].x;
                    }
                    x=f[x];
                }
                cout << g << endl;
            }
        }
    }
    return 0;
}

G - Balanced Lineup

 

For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

Input

Line 1: Two space-separated integers, N and Q
Lines 2.. N+1: Line i+1 contains a single integer that is the height of cow i 
Lines N+2.. NQ+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.

Output

Lines 1.. Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0

//Full of love and hope for life

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#define inf 0x3f3f3f3f
//https://paste.ubuntu.com/

using namespace std;

typedef long long ll;
const ll N=200010;

struct node{
    int ma,mi;
};

node tree[4*N];

void built(int l,int r,int t){
    if(l==r){
        scanf("%d",&tree[t].mi);
        tree[t].ma=tree[t].mi;
        return ;
    }
    int mid=(l+r)/2;
    built(l,mid,2*t);
    built(mid+1,r,2*t+1);
    tree[t].mi=min(tree[2*t].mi,tree[2*t+1].mi);//更新区段
    tree[t].ma=max(tree[2*t].ma,tree[2*t+1].ma);//更新区段
}

int query1(int L,int R,int l,int r,int t){
    if(L<=l&&R>=r){
        return tree[t].ma;
    }
    int mid=(l+r)/2;
    int ans1=0;
    int ans2=0;
    if(L<=mid){
        ans1=query1(L,R,l,mid,2*t);
    }
    if(R>mid){
        ans2=query1(L,R,mid+1,r,2*t+1);
    }
    return max(ans1,ans2);
}

int query2(int L,int R,int l,int r,int t){
    if(L<=l&&R>=r){
        return tree[t].mi;
    }
    int mid=(l+r)/2;
    int ans3=1000010;
    int ans4=1000010;
    if(L<=mid){
        ans3=query2(L,R,l,mid,2*t);
    }
    if(R>mid){
        ans4=query2(L,R,mid+1,r,2*t+1);
    }
    return min(ans3,ans4);
}

int main()
{
    int a,b,x,y;
    cin >> a >> b;
    built(1,a,1);
    while(b--){
        scanf("%d%d",&x,&y);
        printf("%d\n",query1(x,y,1,a,1)-query2(x,y,1,a,1));
    }
    return 0;
}

D - Mayor's posters

The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the posters and introduce the following rules: 

  • Every candidate can place exactly one poster on the wall. 
  • All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown). 
  • The wall is divided into segments and the width of each segment is one byte. 
  • Each poster must completely cover a contiguous number of wall segments.


They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections. 
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall. 

Input

The first line of input contains a number c giving the number of cases that follow. The first line of data for a single case contains number 1 <= n <= 10000. The subsequent n lines describe the posters in the order in which they were placed. The i-th line among the n lines contains two integer numbers l i and ri which are the number of the wall segment occupied by the left end and the right end of the i-th poster, respectively. We know that for each 1 <= i <= n, 1 <= l i <= ri <= 10000000. After the i-th poster is placed, it entirely covers all wall segments numbered l i, l i+1 ,... , ri.

Output

For each input data set print the number of visible posters after all the posters are placed. 

The picture below illustrates the case of the sample input. 

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4

//Full of love and hope for life
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define inf 0x3f3f3f3f
//https://paste.ubuntu.com/

using namespace std;

//typedef long long ll;
typedef long double ld;
const int N = 1e4+10;
const double eps = 1e-6;


/*
离散一般来说有两种
一种就是用映射,那就没有必要新开数组
不用映射的话,就得开数组
*/

int ll[N],rr[N];
bool disv[4*N];
struct node{
    int num;
    int id;
    bool is;//用来标记是左端点还是右端点
} point[2*N];

bool cmp(node a,node b){
     return a.num<b.num;
}

struct pre{
     int l,r,lazy;//col是染成的颜色
}tree[16*N];

/*
template <class T>

inline bool rd(T &ret){
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}

template <class T>

inline void pt(T x){
    if (x <0){
        putchar('-');
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + '0');
}
*/

void pushdown(int t){
    if(tree[t].lazy){
        tree[2*t].lazy=tree[2*t+1].lazy=tree[t].lazy;
        tree[t].lazy=0;
    }
}

void buildtree(int t,int l,int r){
    tree[t].l=l;
    tree[t].r=r;
    if(l==r){
            tree[t].lazy=0;
        return ;
    }
    int mid=(l+r)/2;
    buildtree(2*t,l,mid);
    buildtree(2*t+1,mid+1,r);
    tree[t].lazy=0;
}

void updata(int t,int l,int r,int col){
    int i=tree[t].l;
    int j=tree[t].r;
    if(i==l&&j==r){
        tree[t].lazy=col;
        return ;
    }
    pushdown(t);
    if(r<=tree[2*t].r){
        updata(2*t,l,r,col);
        return ;
    }
    if(l>=tree[2*t+1].l){
        updata(2*t+1,l,r,col);
        return ;
    }
    updata(2*t,l,tree[2*t].r,col);
    updata(2*t+1,tree[2*t+1].l,r,col);
}

int query(int t){
    int i=tree[t].l;
    int j=tree[t].r;
    if(tree[t].lazy&&!disv[tree[t].lazy]){
        disv[tree[t].lazy]=1;
        return 1;
    }
    if(i==j){
        return 0;
    }
    pushdown(t);
	return query(2*t)+query(2*t+1);
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        memset(disv,0,sizeof(disv));
        int a;
        scanf("%d",&a);
        int k=1,u,v;
        for(int i=1;i<=a;i++){
            scanf("%d%d",&u,&v);
            point[k].num=u;
			point[k].id=i;
			point[k++].is=1;
			point[k].num=v;
			point[k].id=i;
			point[k++].is=0;
        }
        //现在点已经存好了,接下来是关键的离散化
		//离散化得先将横坐标排序,也就是先将点按横坐标排序
        sort(point,point+k,cmp);
        int t=-1,g=0;
        for(int i=1;i<k;i++){
            if(point[i].num>t+1){
				g++;
			}
			if(point[i].num!=t){
				t=point[i].num;
				g++;
			}
			if(point[i].is){
				ll[point[i].id]=g;
			}
			else {
                rr[point[i].id]=g;
			}
        }
        buildtree(1,1,g);
        for(int i=1;i<=a;i++){
			updata(1,ll[i],rr[i],i+1);
		}
		printf("%d\n",query(1));
    }
    return 0;
}

//Full of love and hope for life
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define inf 0x3f3f3f3f
//https://paste.ubuntu.com/

using namespace std;

/*
总思路,有1W根棍子。但是区间达到了1QW。
显然得将数据离散化,可以离散到2W。
用个结构体,就可以实现
结构体有个num值,存坐标。还有个bool型分辨起点终点
然后就是循环将所有棍子的信息输入到结构体中。
然后再循环结构体一遍,将棍子的端点坐标进行修改
如何用这些离散后的棍子建树,现在最左边的坐标和最右边的
坐标都可以通过结构体得到。
每个节点我们都设置一个标记。
初始化都标记为-1.当整段被更新,就更新为该棍子的i值
最后查询有多少个棍子可以被看到。
离散化的时候需要注意一点:
比如有数据 (1,10) (1,4) (6,10)
还有数据 (1,10) (1,4) (5,10)
第一组数据离散化后是(1,4) (1,2) (3,4)
第二组数据离散化后是(1,4) (1,2) (3,4)
问题出来了,第二组数据明明是可以看到3张海报的。这样只能看到2张海报了
看了大牛的博客。才找到解决方法。对坐标排序好后,如果前后两个坐标
的差值大于1,就再插入一个点
比如1 4 6 10
就是1 2 4 5 6 7 10
离散1 2 3 4 5 6 7
那么就是(1,7) (1,3) (5,7)
嘿嘿。三段出来了。
*/

typedef long long ll;
typedef long double ld;
const int N = 1e4+10;
const double eps = 1e-6;

int sum;//用来记录总共有多少种海报能够看见
bool disv[4*N];
struct node{
    int num;//用来存坐标
    int id;//用来存这是第几根棍子的坐标
    bool is;
} point[2*N];//至多2W个点

bool cmp(node a,node b){
     return a.num<b.num;
}

struct pre{
     int l,r,lazy;//col用来标记棍子的i值
}tree[16*N];

/*
template <class T>

inline bool rd(T &ret){
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}

template <class T>

inline void pt(T x){
    if (x <0){
        putchar('-');
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + '0');
}
*/

void pushdown(int t){
    tree[2*t].lazy=tree[2*t+1].lazy=tree[t].lazy;
    tree[t].lazy=0;
}

void buildtree(int t,int l,int r){
    tree[t].l=l;
    tree[t].r=r;
    tree[t].lazy=0;
    if(l==r){
        return ;
    }
    int mid=(l+r)/2;
    buildtree(2*t,l,mid);
    buildtree(2*t+1,mid+1,r);
}

void updata(int t,int l,int r,int col){
    int i=tree[t].l;
    int j=tree[t].r;
    if(i==l&&j==r){
        tree[t].lazy=col;
        return ;
    }
    if(tree[t].lazy!=0){
        pushdown(t);
    }
    if(r<=tree[2*t].r){
        updata(2*t,l,r,col);
        return ;
    }
    if(l>=tree[2*t+1].l){
        updata(2*t+1,l,r,col);
        return ;
    }
    updata(2*t,l,tree[2*t].r,col);
    updata(2*t+1,tree[2*t+1].l,r,col);
}

void query(int t,int l,int r){
    int i=tree[t].l;
    int j=tree[t].r;
    if(tree[t].lazy!=0&&i==l&&j==r){
        if(!disv[tree[t].lazy]){
            sum++;
            disv[tree[t].lazy]=1;
            return ;
        }
        return ;//就因为这个return。我狂WA20次。后来还是作灌给我看的~~~
    }
    if(l==r){
        return;
    }
	int mid=(i+j)/2;
	if(r<=mid){
        query(2*t,l,r);
    }
	else if(l>mid){
        query(2*t+1,l,r);
	}
	else{
		query(2*t,l,mid);
		query(2*t+1,mid+1,r);
	}
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int ll[N],rr[N];
        sum=0;
        memset(disv,0,sizeof(disv));
        int a;
        scanf("%d",&a);
        int k=1;
        for(int i=0;i<a;i++){
            scanf("%d%d",&ll[i],&rr[i]);
            point[k].num=ll[i];
			point[k].id=i;
			point[k++].is=true;
			point[k].num=rr[i];
			point[k].id=i;
			point[k++].is=false;
        }
        sort(point,point+k,cmp);
        int t=-1,g=0;
        for(int i=0;i<k;i++){
            if(point[i].num>t+1){
				g++;
			}
			if(point[i].num!=t){
				t=point[i].num;
				g++;
			}
			if(point[i].is){
				ll[point[i].id]=g;
			}
			else {
                rr[point[i].id]=g;
			}
        }
        //将节点读入
        buildtree(1,1,g);
        for(int i=0;i<a;i++){
			updata(1,ll[i],rr[i],i+1);
		}
		query(1,1,g);
		printf("%d\n",sum);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZ --瑞 hopeACMer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值