July 22, 2019 (data structure and search)

Test explode! ! ! ! ! !

Xie good ah, this test into ghosts, afraid to burst this year noip also wilt.

Still not finished, to send summarized, exam today really do not want to say anything ......

Write a serious solution to a problem or it ......

Difficulty of the subject to press a row, the exam only write problem2, a little get at, it would be the first to write explanations of this problem

prob2: collection (set)

Title effect: a tree, each node of the tree corresponds to one set, are empty at the beginning, some operations for each node (element or remove elements added) from root to leaf, the final output node for each set the size of

My approach : tree operation, the order is from the root to the leaves, the first thought is \ (dfs \) wave. Then with respect to the weight of the puncturing elements of the set operation, konjac conceivable approach is to establish a range segment tree, then press (DFS \) \ sequence operation of the node when the node is a complete traverse the subtree rooted after , reduction of the operation node, this will not affect the output of other subtrees answers.

Looks like \ (zsb \) chiefs have only \ (dfs \) method to achieve, but the idea seems almost blown up a few other questions have to order, there is no way to see him up

Well, I did not expect this method \ (RE \) fly. Think about it, in fact, should have thought, even weights tree line, the number of nodes should also open \ (4 \) times, how many times! ! ! ! !

ririririri ......

Khan, under this test really fly,

Code is as follows (End of change):

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define xx 110000
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
struct line_tree{int l,r,sz,ans;}lt[xx<<2];
int num=0,res[xx],now;
vector<int>e[xx],ee[xx],eee[xx];
bool vis[xx];
inline void build(int k,int i,int j)
{
    lt[k].l=i;lt[k].r=j;
    if(i==j) return;
    int q=k<<1,mid=(i+j)>>1;
    build(q,i,mid);
    build(q+1,mid+1,j);
}
inline void up(int k)
{
    int q=k<<1;
    lt[k].ans=lt[q].ans+lt[q+1].ans;
}
inline void add(int k,int x,int c)
{
    if(lt[k].l==lt[k].r)
    {
        now=lt[k].sz;
        lt[k].sz+=c;
        lt[k].sz=max(lt[k].sz,0);
        lt[k].sz=min(lt[k].sz,1);
        lt[k].ans=lt[k].sz?1:0;
        return;
    }
    int q=k<<1,mid=lt[q].r;
    if(x<=mid) add(q,x,c);
    else add(q+1,x,c);
    up(k);
}
inline void change(int k,int x,int c)
{
    if(lt[k].l==lt[k].r)
    {
        lt[k].sz=c;
        lt[k].ans=lt[k].sz?1:0;
        return;
    }
    int q=k<<1,mid=lt[q].r;
    if(x<=mid) change(q,x,c);
    else change(q+1,x,c);
    up(k);
}
inline void dfs(int g)
{
    fur(i,0,(int)ee[g].size()-1)
    {
        if(ee[g][i]<0) add(1,-ee[g][i],-1);
        else add(1,ee[g][i],1);
        eee[g].push_back(now);
    }
    res[g]=lt[1].ans;
    fur(i,0,(int)e[g].size()-1) if(!vis[e[g][i]]) vis[e[g][i]]=true,dfs(e[g][i]);
    fur(i,0,(int)ee[g].size()-1)
    {
        if(ee[g][i]<0) change(1,-ee[g][i],eee[g][i]);
        else change(1,ee[g][i],eee[g][i]);
    }
}
int main()
{
    int n=in;
    fur(i,1,n-1)
    {
        int x=in,y=in;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    fur(i,1,n)
    {
        int k=in;
        fur(j,1,k)
        {
            int x=in;
            ee[i].push_back(x);
        }
    }
    build(1,1,n);
    vis[1]=true;
    dfs(1);
    fur(i,1,n) printf("%d\n",res[i]);
    return 0;
}

Positive Solutions : thoughts above, but the data segment tree structures becomes a barrel range, so that \ (O (1) \) modifications.

这下复杂度就对了,时间空间都舒服很多,而且不会有恶心的情况,代码如下:  
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define xx 110000
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int num=0,res[xx],before;
vector<int>e[xx],ee[xx],eee[xx];
bool vis[xx],cnt[xx];
inline void dfs(int g)
{
    fur(i,0,(int)ee[g].size()-1)
    {
        before=cnt[abs(ee[g][i])];
        if(ee[g][i]<0) cnt[-ee[g][i]]=false;
        else cnt[ee[g][i]]=true;
        num+=(cnt[abs(ee[g][i])]-before);
        eee[g].push_back(before);
    }
    res[g]=num;
    fur(i,0,(int)e[g].size()-1) if(!vis[e[g][i]]) vis[e[g][i]]=true,dfs(e[g][i]);
    fur(i,0,(int)ee[g].size()-1)
    {
        before=cnt[abs(ee[g][i])];
        if(ee[g][i]<0) cnt[-ee[g][i]]=eee[g][i];
        else cnt[ee[g][i]]=eee[g][i];
        num+=(cnt[abs(ee[g][i])]-before);
    }
}
int main()
{
    int n=in;
    fur(i,1,n-1)
    {
        int x=in,y=in;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    fur(i,1,n)
    {
        int k=in;
        fur(j,1,k)
        {
            int x=in;
            ee[i].push_back(x);
        }
    }
    vis[1]=true;
    dfs(1);
    fur(i,1,n) printf("%d\n",res[i]);
    return 0;
}

prob1: median (median)

Title effect: 1 ~ n a given arrangement, the product of each inquiry about the median interval m and the ends of the section containing an odd number of elements, and

40 sub-section points : This section is divided to the very foot, 1k less than the amount of code a full 40 minutes, which say nothing, pure violence, every rearrangement, find the median. Time complexity \ (O (n ^ 3logn) \)

Violence engage in law : in \ (xgzc \) improved konjac unformed fantasy with the help of big brother, is easy to know: a total of \ (\ dfrac {n ^ 2 } {2} \) intervals, the statistical median, then konjac want to find the entire half wave interval \ (MID \) a small value, say that big brother but the time complexity is \ (O (n-2logn ^) \) . Also constant is big, bad cards, it is a failure. The two stacks (a root, a small root) median can be done to maintain the same degree of complexity, and the constant can be negligibly small. Also, because this question can open \ (O2 \) , \ (the n-\) range is small ( \ (<= 1E4 \) ), it can be so violent show too.

Well, it has not been, stuck up, data or big, too strong qwq seniors

code show as below:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define xx 11000
#define ll long long
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
priority_queue<ll>e;
priority_queue<ll,vector<ll>,greater<ll> >f;
ll a[xx],ans=0;
int main()
{
    int n=in;
    fur(i,1,n) a[i]=in;
    fur(i,1,n)
    {
        while(!e.empty()) e.pop();
        while(!f.empty()) f.pop();
        e.push(a[i]);
        ans+=i*i*e.top();
        for(int j=i+2;j<=n;j+=2)
        {
            int now=0;
            fur(k,j-1,j)
            {
                if(!now)
                {
                    if(f.empty()||a[k]<=f.top()) e.push(a[k]);
                    else
                    {
                        e.push(f.top());
                        f.pop();
                        f.push(a[k]);
                    }
                    now++;
                }
                else
                {
                    if(a[k]>=e.top()) f.push(a[k]);
                    else
                    {
                        f.push(e.top());
                        e.pop();
                        e.push(a[k]);
                    }
                }
            }
            ans+=i*j*e.top();
        }
    }
    printf("%lld\n",ans);
    return 0;
}

Positive solution : open a doubly linked list, you can do the median \ (O (1) \) transfer. And I thought the same, not much to say, that much is tears. The Code (solution to a problem with the seniors, can not read, forget):

#include <iostream>
#include <vector>
using namespace std;
typedef long long int64;
int main() {
    freopen("median.in","r",stdin);
    freopen("median.out","w",stdout);
    int n; cin >> n;
    vector<int> element(n);
    for (int i = 0; i < n; i += 1) {
        cin >> element[i];
    }
    vector<pair<int, int>> neighbours(n + 1);
    int64 result = 0;
    for (int i = 0; i < n; i += 1) {
         //如果索引在[i,n]范围内,则该值有效 
        vector<bool> valid(n + 1, false);
        for (int j = i; j < n; j += 1) {
            valid[element[j]] = true;
        }
        valid[n + 1] = true;
        int last = 0;
        //值的数目>中间值,较低值的数目<=中间值
        //mid->中间值
        int bigger = (n - i), lower = 0, mid = 0;
        //  计算每个值,左边和右边的下一个有效值 
        for (int j = 1; j <= n; j += 1) {
            if (not valid[j]) {
                continue;
            }
            if (bigger > lower) {
                mid = j;
                bigger -= 1;
                lower += 1;
            }
            // 最后一个元素将是当前元素左边的元素
            // 最后一个元素右边的元素将是这个元素
            neighbours[j].first = last;
            neighbours[last].second = j;
            last = j;
        }
        for (int j = n -1 ; j >= i; j -= 1) {
            if (lower == bigger + 1) {
                // this can be any formula, whatsoever
                result += (int64) (j + 1) * (i + 1) * mid;
            } 
            // 值位于擦除值的左侧和右侧
            int left = neighbours[element[j]].first;
            int right = neighbours[element[j]].second;
            // 从“likef列表”中删除此列表
            neighbours[left].second = right;
            neighbours[right].first = left;
            // 更新中间值、较大或较小的值。
            if (element[j] == mid) {
                bigger -= 1;
                mid = right;
            } else if (element[j] < mid) {
                lower -= 1;
            } else {
                bigger -= 1;
            }
            while (lower > bigger) {
                mid = neighbours[mid].first;
                bigger += 1;
                lower -= 1;
            }

            // move the median to the right
            while (bigger > lower) {
                mid = neighbours[mid].second;
                bigger -= 1;
                lower += 1;
            }
        }
    }
    cout << result << '\n';
    return 0;
}

Other solution : Please allow me to introduce you a grand \ (yyz \) chiefs of the solution, and simply beautiful Mo team has the same purpose, the same is by (O (1) \) \ to delete, add value to transfer \ ( MID \) the location pointed to achieve a solution with the same excellent positive \ (O (n ^ 2) \) algorithm, step burst \ (STD \) . \ (orz \) ......

For details, see the code:

#include<iostream>
#include<cstdio>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define int long long
#define xx 10010
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int cnt[xx],a[xx];
signed main()
{
    int n=in;
    fur(i,1,n) a[i]=in;
    int l=1,r=0,mid=0,cnnt=0,ans=0;
    fur(tl,1,n)
    {
        for(int tr=tl;tr<=n;tr+=2)
        {
            while(l<tl)
            {
                if(a[l]<=mid) --cnnt;
                --cnt[a[l++]];
            }
            while(r<tr)
            {
                ++r;
                if(a[r]<=mid) ++cnnt;
                ++cnt[a[r]];
            }
            while(r>tr)
            {
                if(a[r]<=mid) --cnnt;
                --cnt[a[r--]];
            }
            int need=((tr-tl)>>1)+1;
            if(need==1)
            {
                mid=a[tl];
                cnnt=1;
                ans+=tr*tl*mid;
                continue;
            }
            while(cnnt<need) cnnt+=cnt[++mid];
            while(cnnt>need)
            {
                if(cnnt-cnt[mid]<need) break;
                cnnt-=cnt[mid--];
            }
            while(cnt[mid]==0) --mid;
            ans+=tl*tr*mid;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

prob4: Star (stars)

Title effect: a given number of points on a plane, each point has its corresponding weight value, to find the maximum weight matrix and sized.

Scanning line bare title (Unfortunately, I will not

Or give 40 minutes violent approach it:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define xx 55000
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
struct point{int x,y,z;}dot[xx];
int ans=0;
inline bool cmp(point a,point b){return (a.x^b.x)?(a.x<b.x):(a.y<b.y);}
int main()
{
    int n=in,w=in,h=in;
    fur(i,1,n)
    {
        dot[i].x=in;
        dot[i].y=in;
        dot[i].z=in;
    }
    sort(dot+1,dot+n+1,cmp);
    fur(i,1,n)
    {
        int j=i+1,tmp=dot[i].z;
        while(j<=n&&dot[j].x-dot[i].x<=w)
        {
            if(dot[j].y-dot[i].y<=h&&dot[j].y>=dot[i].y) tmp+=dot[j].z;
            j++;
        }
        int j1=i+1,tmp1=dot[i].z;
        while(j1<=n&&dot[j1].x-dot[i].x<=w)
        {
            if(dot[i].y-dot[j1].y<=h&&dot[j1].y<=dot[i].y) tmp1+=dot[j1].z;
            j1++;
        }
        ans=max(ans,max(tmp,tmp1));
    }
    printf("%d\n",ans);
    return 0;
}

Well, the water is used to water the number of words the program, or to get to the next

Positive Solution : Add scan line segment tree optimization, as detailed in the code:

#include <cstdio>
#include<cstring>
#include <iostream>
#include <algorithm>
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
typedef long long ll;
ll geti(){
    char ch=getchar(),k=1;ll ret=0;
    while((ch<'0' || ch>'9') && ch!='0')ch=getchar();
    if(ch=='-')k=0,ch=getchar();
    while(ch>='0' && ch<='9')ret=ret*10+ch-'0',ch=getchar();
    return k?ret:-ret;
}
const int maxn = 100000 + 1000;
struct XDS{
    ll mx[maxn*8],lazy[maxn*8];
    void pushdown(int x){
        mx[ls]+=lazy[x];mx[rs]+=lazy[x];
        lazy[ls]+=lazy[x];lazy[rs]+=lazy[x];
        lazy[x]=0;
    }
    void update(int x,int l,int r,int xl,int xr,ll v){
        if(xl==l && r==xr){
            mx[x]+=v;lazy[x]+=v;return;
        }
        int mid=(l+r)>>1;
        if(xr<=mid)update(ls,l,mid,xl,xr,v);
        else if(xl>mid)update(rs,mid+1,r,xl,xr,v);
        else update(ls,l,mid,xl,mid,v),update(rs,mid+1,r,mid+1,xr,v);
        mx[x]=max(mx[ls],mx[rs])+lazy[x];
    }
    ll query(int x,int l,int r,int xl,int xr){
        if(l==xl && r==xr){
            return mx[x];
        }
        int mid=(l+r)>>1;
        if(xr<=mid)return query(ls,l,mid,xl,xr)+lazy[x];
        else if(xl>mid)return query(rs,mid+1,r,xl,xr)+lazy[x];
        else return max(query(ls,l,mid,xl,mid),query(rs,mid+1,r,mid+1,xr))+lazy[x];
    }
}t;
int n,w,h;
struct star{
    ll x,y,ty,l;
}a[maxn];
ll hs[maxn];
bool cmpx(const star &x,const star &y){return x.x<y.x;}
bool cmpy(const star &x,const star &y){return x.ty<y.ty;}
int main()
{
        scanf("%d%d%d",&n,&w,&h)
        for(int i=1;i<=n;i++)
        {
            a[i*2-1].x=geti();a[i*2-1].ty=geti();a[i*2-1].l=geti();
            a[i*2].x=a[i*2-1].x+w+1;a[i*2].ty=a[i*2-1].ty;a[i*2].l=-a[i*2-1].l;
        }
        n=n*2;
        sort(a+1,a+1+n,cmpy);
        int s=0;
        for(int i=1;i<=n;i++)
        {
            if(i!=1 && a[i].ty==a[i-1].ty) a[i].y=s;
            else
            {
                if(a[i].ty-hs[s]>1) ++s,hs[s]=hs[s-1]+1;
                ++s;hs[s]=a[i].ty;
                a[i].y=s;
            }
        }
        hs[++s]=a[n].ty+1;
        sort(a+1,a+1+n,cmpx);
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            int l=a[i].y,r=s,mid,rt=-1;
            ll cur=a[i].ty+h;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(hs[mid]<=cur) rt=mid,l=mid+1;
                else r=mid-1;
            }
            t.update(1,1,s,a[i].y,rt,a[i].l);
            if(a[i].x!=a[i+1].x || i==n) ans=max(ans,t.query(1,1,s,1,s));
        }
        printf("%lld\n",ans);
        return 0;   
}

prob3: Starcraft (craft)

Topic effect: Given a (c * r \) \ matrix, which can have a grid with not two, given the hero with two enemy positions with both the blood, seek if you can win the game and win the minimum number of rounds of the game

\ (MDzhizhang \), Seniors say this problem is the road \ (sb \) burst search can be found off the hook to the point, what do not want to say. Seems to be no time, the last direct \ (kuai \) Forget solution to a problem of (standard process used \ (dp \) ):

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
LL gi () {
    LL ret=0; char ch=getchar();
    while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    char c=ch=='-'?getchar():ch;
    while(c>='0' && c<='9') ret=ret*10+c-'0',c=getchar();
    return ch=='-'?-ret:ret;
}
int n,m,tl,pos[37][37],w[37][37],near[37][37],h_m,h_z,dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
int dp[55][37][37][37][18];
char mp[7][7];
int go (int p,int d) {
    int x = (p-1)/m, y = (p-1)%m;
    int nx = x + dx[d], ny = y + dy[d];
    if(nx < 0 || nx > n || ny < 0 || ny > m || mp[nx][ny]=='1') return -1;
    return pos[nx][ny];
}
int zgo (int p,int g) {
    if(near[p][g] || !p) return p;
    int res = -1, dis = 1e9;
    for(int i=0;i<=3;i+=1) {
        int c = go(p,i);
        if(c==-1) continue;
        if(w[c][g] < dis) dis = w[c][g], res = c;
    }
    if(dis > 100) return p;
    return res;
}
void upd (int &x, int y) {
    x = x < y ? x : y;
}
int main (int argc, char* argv[]) {
    freopen("craft.in","r",stdin);
    freopen("craft.out","w",stdout);
    n = gi(), m = gi(), tl = gi();
    for(int i=0;i<n;i+=1) scanf("%s",mp[i]);
    h_m = gi(); h_z = gi();
    int p1 = -1, p2 = -1, p3 = -1;
    for(int i=0;i<n;i+=1) {
        for(int j=0;j<m;j+=1) {
            pos[i][j] = i*m+j+1;
            if(mp[i][j]=='z' || mp[i][j]=='Z') {
                if(p2 == -1) p2 = pos[i][j]; else p3 = pos[i][j];
            }
            else if(mp[i][j]=='M') p1 = pos[i][j];
        }
    }
    memset(w,60,sizeof w);
    for(int i=0;i<n;i+=1) {
        for(int j=0;j<m;j+=1) {
            if(mp[i][j] == '1') continue;
            if(i && mp[i-1][j] != '1') w[pos[i][j]][pos[i-1][j]] = 1;
            if(i!=n-1 && mp[i+1][j] != '1') w[pos[i][j]][pos[i+1][j]] = 1;
            if(j && mp[i][j-1] != '1') w[pos[i][j]][pos[i][j-1]] = 1;
            if(j!=m-1 && mp[i][j+1] != '1') w[pos[i][j]][pos[i][j+1]] = 1;
            w[pos[i][j]][pos[i][j]] = 0;
        }
    }
    int sz = n*m;
    for(int i=1;i<=sz;i+=1) {
        for(int d=0;d<=3;d+=1)
            if(go(i,d) != -1) near[i][go(i,d)] = 1;
    }
    for(int k=1;k<=sz;k+=1)
        for(int i=1;i<=sz;i+=1)
            for(int j=1;j<=sz;j+=1) w[i][j] = min(w[i][j], w[i][k] + w[k][j]);
    memset(dp,60,sizeof dp);
    dp[0][p1][p2][p3][h_m] = h_z * 2;
    dp[0][p1][p3][p2][h_m] = h_z * 2;
    for(int i=0;i<tl;i+=1)
        for(int t1=1;t1<=sz;t1+=1)
            for(int t2=0;t2<=sz;t2+=1)
                for(int t3=0;t3<=sz;t3+=1)
                    for(int h=1;h<=h_m;h+=1) {
                        int cur = dp[i][t1][t2][t3][h];
                        if(cur > 100) continue;
                        // 1. move
                        for(int d=0;d<=3;d+=1) {
                            int n1 = go(t1,d);
                            if(n1 == -1 || n1 == t2 || n1 == t3) continue;
                            int v = 0;
                            int n2 = zgo(t2,n1), n3 = zgo(t3,n1);
                            if(near[t2][n1]) ++v;
                            if(near[t3][n1] && t2 != t3 && cur > h_z) ++v;
                            if(h-v > 0) {
                                upd(dp[i+1][n1][n2][n3][h-v], cur);
                            }
                        }
                        // 2. attack
                        int n2 = zgo(t2,t1), n3 = zgo(t3,t1);
                        if(cur == 1) {
                            printf("WIN\n%d",i+1); exit(0);
                        }
                        int v = 0;
                        if(near[t2][t1]) ++v;
                        if(near[t3][t1] && t2 != t3 && cur-1 > h_z) ++v;
                        if(h-v > 0) {
                            if(cur-1 > h_z) {
                                upd(dp[i+1][t1][n2][n3][h-v], cur-1);
                            }
                            else {
                                upd(dp[i+1][t1][n2][0][h-v], cur-1);
                            }
                        }
                    }
    puts("LOSE");
    return 0;
}

We do not want to graph theory, water tomorrow

Guess you like

Origin www.cnblogs.com/ALANALLEN21LOVE28/p/11312970.html