Luo Gu P3998 [SHOI2013] micro-Bo

Luo Gu P3998 [SHOI2013] micro-Bo

Luo Gu Portal

Title Description

SH microblogging just opened a total of n users (1Ln label), in this short month's time,

They are frequent users, a total of m records in chronological order:

! x 表示用户x发了一条微博;
+ x y 表示用户x和用户y成为了好友
− x y 表示用户x和用户y解除了好友关系

When a user micro-Bo, when all his friends (direct relation) will see his message.

Everyone assumed that between the beginning of the relationship are not friends, are also recorded when legal (ie + xy x and

y must not friends, and - xy x and y must be friends).

After asking this m record the occurrence, each user to see how many messages.

Input Format

Line 1 two integers n, m.

Subsequently m rows and m is read in chronological order records, each record format as the title, with

Separated by a space.

Output Format

Output line separated by a space of n number (no space end of the line), represents the i-th user to see the last i

A few messages.

Sample input and output

Input # 1 copy

Output # 1 copy

Description / Tips

n<=200000

m<=500000

answer:

2019 pairs of ten simulation game (konjac are shivering on the test exam cultural studies)

Later @littleseven 7 brother took me to do this question ...

At that time just 50 points out of the idea of violence, and very easy to think, it is to open an array \ (f [i] [J] \) (open bool array, you can save some space, let it able to open \ (10 ^ 8 \) ), represents \ (i \) , \ (J \) are not friends. Then every time someone a message, put it in the answer to all my friends \ (+ 1 \) .

50pts code is as follows:

#include<cstdio>
#include<iostream>
using namespace std;
int n,m;
bool f[10000][10000];
int ans[10000];
int main()
{
    // freopen("qq.in","r",stdin);
    // freopen("qq.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        char ch;
        cin>>ch;
        if(ch=='+')
        {
            scanf("%d%d",&x,&y);
            f[x][y]=1,f[y][x]=1;
        }
        else if(ch=='-')
        {
            scanf("%d%d",&x,&y);
            f[x][y]=0,f[y][x]=0;
        }
        else
        {
            scanf("%d",&x);
            for(int j=1;j<=n;j++)
                if(f[x][j])
                    ans[j]++;
        }
    }
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    return 0;
}

Then tell us about a positive solution.

In fact, I thought violence if further in-depth look at the top of which is a positive solution, ideas are: Record friend, cumulative answer . So why the above code called the violence, the following code is called positive solution, because the complexity is not the same. Positive solution can run larger data. So by this question, but also teach us a answer techniques in the examination room: When we can only come up with the idea of violence, think about how violence optimization algorithm by known means, maybe engage in a practice came out positive solutions .

Syria gossip less, straight to the point:

We have come to the idea of violence: Record friend, cumulative answer. We just used a friend's record would be to open a matrix array. But this is certainly no less open space ( \ (n-\ Le 2 \ ^ 10. 5 Times \) ). So we began to think: What can we make of \ (1-n \) Everyone record a sequence, but do easily add and delete it?

\ (STL \) Dafa: \ (the SET \) container.

Use the \ (set \) code becomes 80 points, remaining two points \ (TLE \) a.

80pts code is as follows:

#include<cstdio>
#include<iostream>
#include<set>
using namespace std;
const int maxn=2*1e5+1;
int n,m;
set<int> s[maxn];
set<int>::iterator it;
int ans[maxn];
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
    int x=0,f=1;
    char ch=nc();
    while(ch<48){if(ch=='-')f=-1;ch=nc();}
    while(ch>47)    x=x*10+ch-'0',ch=nc();
    return x*f;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++)
    {
        int x,y;
        char ch=nc();
        if(ch=='+')
        {
            x=read();y=read();
            s[x].insert(y);
            s[y].insert(x);
        }
        else if(ch=='-')
        {
            x=read();y=read();
            s[x].erase(y);
            s[y].erase(x);
        }
        else
        {
            x=read();
            for(it=s[x].begin();it!=s[x].end();it++)
                ans[*it]++;
        }
    }
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    return 0;
}

Plus read optimization, however, did not use ......

Then we continue to think about ......

Since \ (TLE \) , then obviously the answer to the question of when statistics. 80, when the answer to the idea of using statistics from start to finish to the iterator \ (X \) of each answer \ (1 + \) , this complexity is almost \ (O (n \ times m ) \) apparently No way.

So we consider this: Since a plus not once, once we add a bunch.

Concrete realization of the principle is this:

Imagine, now you are a contractor, you have to give a person working, wages a dollar a day. Then one day the man quit, so you give him a settlement with his wages these days, you happily blow up ~

Migration to this question: When you blog more each time, the equivalent of the site did live another day, you want to give your workers (friends) made a dollar of wages. Do you think one day at a settlement too much trouble, so you recorded the first day of each worker to work day and the day of retirement, then with the money settlement to them.

This is a differential thought it!

We opened an array \ (cnt [i] \) , expressed up to now, \ (i \) has made a number of microblogging. When a person adds \ (i \) friend, then record what time this person added \ (i \) , the specific method is to \ (cnt [i] \) is subtracted, when removed \ ( i \) friend, when the then delete \ (cnt [i] \) added back. In this way, \ (cnt [i_1] \) and \ (cnt [i_2] \) difference on behalf of the people to become \ (i \) the number of micro-blog friends received within this period of time.

Of course, this processed \ (m \) th to ask when there will be some other people who are still friends. Our statistical algorithm only answer deleted when friends. This is equivalent to one day the site went out of business, but there are still some workers to follow you, even when your pants also have to give them money.

This question is when we do not need the pants, just in processed \ (m \) plus double after operations \ (for \) loop statistical forced to answer.

(Personally I think that a good image ah this analogy, if you think it's helpful for you to understand, that I easily recommend to pray and praise ~)

100pts code is as follows:

#include<cstdio>
#include<set>
#include<iostream>
using namespace std;
const int maxn=2*1e5+1;
int n,m;
int cnt[maxn],ans[maxn];
set<int> s[maxn];
set<int>::iterator it;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        char opt;
        cin>>opt;
        int x,y;
        if(opt=='!')
        {
            scanf("%d",&x);
            cnt[x]++;
        }
        else if(opt=='+')
        {
            scanf("%d%d",&x,&y);
            ans[x]-=cnt[y];
            ans[y]-=cnt[x];
            s[x].insert(y);
            s[y].insert(x);
        }
        else
        {
            scanf("%d%d",&x,&y);
            ans[x]+=cnt[y];
            ans[y]+=cnt[x];
            s[x].erase(y);
            s[y].erase(x);
        }
    }
    for(int i=1;i<=n;i++)
        for(it=s[i].begin();it!=s[i].end();it++)
            ans[i]+=cnt[*it];
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/fusiwei/p/11693977.html
Recommended