zoukankan      html  css  js  c++  java
  • 【分块入门1-9】--分块大法好

    分块一:

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。

      普通分块水过

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    int n, a[100100], len,tag[100100], posit[100100];
    void change(int l, int r, int c) {
        if (posit[l]==posit[r]) {
            for (int i = l; i <= r; i++) {
                a[i] += c;
            }
            return;
        }
        for(int i=l; i<=posit[l]*len; i++) a[i] += c;
        for(int i=posit[l] + 1; i<= posit[r]-1; i++) tag[i] += c;
        for(int i=(posit[r] - 1)*len +1;i <= r; i++) a[i] += c;
    }
    int main() {
        scanf("%d", &n);
        len = sqrt(n);
        for (int i = 1; i <= n; i++) {
           scanf("%d", &a[i]);
    	   posit[i] = (i - 1) / len + 1;
         }
        int opt, l, r, c;
        while (n--) {
            scanf("%d%d%d%d", &opt, &l, &r, &c);
            if (!opt) {
                change(l,r,c);
            } else {
                printf("%d
    ",a[r]+tag[posit[r]]);
            }
        }
        return 0;
    }

    分块二:

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数。

        块内sort,lower_bound,加一个数组,辅助残块sort,因为原序列不能变

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define int long long
    #define MAXN 100000
    using namespace std;
    int n,opt,a[MAXN],b[MAXN],pos[MAXN],tag[MAXN],len;
    void change(int l,int r,int c)
    {
    	if(pos[l]==pos[r])
    	{
    		for(int i=l;i<=r;i++)a[i]+=c;
    		for(int i=(pos[l]-1)*len+1;i<=min(pos[l]*len,n);i++)b[i]=a[i];
    		sort(b+(pos[l]-1)*len+1,b+1+min(n,pos[l]*len));
    		return;
    	}
    	for(int i=l;i<=pos[l]*len;i++)a[i]+=c;
    	for(int i=(pos[l]-1)*len+1;i<=pos[l]*len;i++)b[i]=a[i];
    	sort(b+(pos[l]-1)*len+1,b+1+pos[l]*len);
    	for(int i=pos[l]+1;i<=pos[r]-1;i++)tag[i]+=c;
    	for(int i=(pos[r]-1)*len+1;i<=r;i++)a[i]+=c;
    	for(int i=(pos[r]-1)*len+1;i<=min(pos[r]*len,n);i++)b[i]=a[i];
    	sort(b+(pos[r]-1)*len+1,b+1+min(pos[r]*len,n));
    }
    int query(int l,int r,int c)
    {
    	int ans=0;
    	if(pos[l]==pos[r])
    	{
    		for(int i=l;i<=r;i++)
    		{
    			if(a[i]+tag[pos[i]]<c*c)ans++;
    		}
    		return ans;
    	}
    	for(int i=l;i<=pos[l]*len;i++)
    	{
    		if(a[i]+tag[pos[i]]<c*c)ans++;
    	}
    	for(int i=pos[l]+1;i<=pos[r]-1;i++)ans+=lower_bound(b+(i-1)*len+1,b+(i*len)+1,c*c-tag[i])-b-((i-1)*len+1);
    	for(int i=(pos[r]-1)*len+1;i<=min(n,r);i++)
    	{
    		if(a[i]+tag[pos[i]]<c*c)ans++;
    	}
    	return ans;
    }
    signed main()
    {
    	scanf("%lld",&n);
    	len=sqrt(n);
    	for(int i=1;i<=n;i++)pos[i]=(i-1)/len+1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		b[i]=a[i];
    	}
    	for(int i=1;i<=pos[n];i++)sort(b+(i-1)*len+1,b+1+min(i*len,n));
    	for(int i=1,l,r,c;i<=n;i++)
    	{
    		scanf("%lld%lld%lld%lld",&opt,&l,&r,&c);
    		if(opt==0)
    		{
    			change(l,r,c);
    		}
    		if(opt==1)
    		{
    			
    			printf("%lld
    ",query(l,r,c));
    		}
    	}
    	return 0;
    }
    

      

    分块三:

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的前驱(比其小的最大元素)。

     块内sort加lower_bound查询

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #define N 500500
    using namespace std;
    
    inline long long read() {
        int x = 0, f = 1;
        char s = getchar();
        while (s < '0' || s > '9') {
            if (s == '-')
                f = -1;
            s = getchar();
        }
        while (s >= '0' && s <= '9') {
            x = x * 10 + s - '0';
            s = getchar();
        }
        return x * f;
    }
    
    int n, len;
    int a[N], b[N];
    int tag[N], lz[N];
    int L[N], R[N];
    
    inline void change(int l, int r, int c) {
        if (tag[l] == tag[r]) {
            for (int i = l; i <= r; i++) a[i] += c;
            for (int i = L[tag[l]]; i <= R[tag[r]]; i++) b[i] = a[i];
            sort(b + L[tag[l]], b + R[tag[l]] + 1);
            return;
        }
        for (int i = l; i <= R[tag[l]]; i++) a[i] += c;
        for (int i = L[tag[l]]; i <= R[tag[l]]; i++) b[i] = a[i];
        sort(b + L[tag[l]], b + R[tag[l]] + 1);
        for (int i = tag[l] + 1; i < tag[r]; i++) lz[i] += c;
        for (int i = L[tag[r]]; i <= r; i++) a[i] += c;
        for (int i = L[tag[r]]; i <= R[tag[r]]; i++) b[i] = a[i];
        sort(b + L[tag[r]], b + R[tag[r]] + 1);
    }
    
    inline int ask(int l, int r, int c) {
        int ans = -1;
        if (tag[l] == tag[r]) {
            for (int i = l; i <= r; i++)
                if (a[i] + lz[tag[i]] < c)
                    ans = max(ans, a[i] + lz[tag[i]]);
            return ans;
        }
        for (int i = l; i <= R[tag[l]]; i++)
            if (a[i] + lz[tag[i]] < c)
                ans = max(ans, a[i] + lz[tag[i]]);
        for (int i = tag[l] + 1; i < tag[r]; i++) {
            int k = lower_bound(b + L[i], b + R[i] + 1, c - lz[i]) - b;
            if (k != L[i])
                if (b[k - 1] + lz[i] < c)
                    ans = max(ans, b[k - 1] + lz[i]);
        }
        for (int i = L[tag[r]]; i <= r; i++)
            if (a[i] + lz[tag[i]] < c)
                ans = max(ans, a[i] + lz[tag[i]]);
        return ans;
    }
    
    int main() {
        n = read();
        int len = sqrt(n);
        for (int i = 1; i <= n; i++) tag[i] = (i - 1) / len + 1;
        for (int i = 1; i <= tag[n]; i++) L[i] = R[i - 1] + 1, R[i] = min(n, L[i] + len - 1);
        for (int i = 1; i <= n; i++) a[i] = read(), b[i] = a[i];
        for (int i = 1; i <= tag[n]; i++) sort(b + L[i], b + R[i] + 1);
        for (int i = 1; i <= n; i++) {
            int opt = read(), l = read(), r = read(), c = read();
            if (opt == 0)
                change(l, r, c);
            else
                printf("%d
    ", ask(l, r, c));
        }
        return 0;
    }
    

      

    分块四:

    给出一个长为n的数列,以及n个操作,操作涉及区间加法,区间求和。

         打标记,其余暴力

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #define MAXN 1000010
    #define int long long
    int a[MAXN],tag[MAXN],le[MAXN],ri[MAXN],sum[MAXN],val[MAXN],pos[MAXN],len;
    void change(int l,int r,int c)
    {
    	if(pos[l]==pos[r])
    	{
    		for(int i=l;i<=r;i++)
    		{
    			a[i]+=c;val[pos[i]]+=c;
    		}
    		return;
    	}
    	for(int i=l;i<=ri[pos[l]];i++) a[i]+=c , val[pos[i]]+=c;
    	for(int i=pos[l]+1;i <= pos[r]-1 ; i++)tag[i]+=c;
    	for(int i=le[pos[r]];i<=r;i++) a[i]+=c , val[pos[i]]+=c;
    }
    int query(int l,int r,int c)
    {
    	int mod=c+1,ans=0;
    	if(pos[l]==pos[r])
    	{
    		for(int i=l;i<=r;i++)ans+=(a[i]+tag[pos[i]]),ans%=mod;
    		return ans;
    	}
    	for(int i=l;i<=ri[pos[l]];i++)ans+=(a[i]+tag[pos[i]]),ans%=mod;
    	for(int i=pos[l]+1;i<=pos[r]-1;i++)
    	{
    		ans+=(val[i]+tag[i]*len);
    		ans%=mod;
    	}
    	for(int i=le[pos[r]];i<=r;i++)ans+=(a[i]+tag[pos[i]]),ans%=mod;
    	return ans;
    }
    signed main()
    {
    	int n;
    	scanf("%lld",&n);
    	len=sqrt(n);
    	for(int i=1;i<=n;i++)
    	{
    		pos[i]=(i-1)/len+1;
    		scanf("%lld",&a[i]);
    		sum[i]=sum[i-1]+a[i];
    	}
    	for(int i=1;i<=pos[n];i++)
    	{
    		le[i]=(i-1)*len+1;
    		ri[i]=i*len;
    		val[i]=sum[ri[i]]-sum[le[i]-1];
    	}
    	for(int i=1,opt,l,r,c;i<=n;i++)
    	{
    		scanf("%lld%lld%lld%lld",&opt,&l,&r,&c);
    		if(opt==0)change(l,r,c);
    		if(opt==1)
    		{
    			printf("%lld
    ",query(l,r,c));
    		}
    	}
    	return 0;
    }

    分块五:

    给出一个长为n的数列,以及n个操作,操作涉及区间开方,区间求和。

      线段树,标记维护区间是否都为一

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cmath>
    #define MAXN 5100000
    #define int long long
    using namespace std;
    long long tr[MAXN*4],n,a[MAXN*2];
    bool vis[MAXN*4];
    void updata(int k)
    {
    	tr[k]=tr[k<<1]+tr[k<<1|1];
    	if(vis[k<<1]==1 && vis[k<<1|1]==1)vis[k]=1;
    	return;
    }
    void change(int k,int l,int r,int x,int y)
    {
    	if(vis[k])return;
    	if(l>=x && r<=y && l==r)
    	{
    		tr[k]=sqrt(tr[k]);
    		if(tr[k]==1||tr[k]==0)vis[k]=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid)change(k<<1,l,mid,x,y);
    	if(y>mid)change(k<<1|1,mid+1,r,x,y);
    	updata(k);
    }
    int ask(int k,int l,int r,int x,int y)
    {
    	if(l>=x && r<=y)return tr[k];
    	int mid=(l+r)>>1,ans=0;
    	if(x<=mid)ans+=ask(k<<1,l,mid,x,y);
    	if(y>mid)ans+=ask(k<<1|1,mid+1,r,x,y);
    	return ans;
    }
    void  build(int k,int l,int r)
    {
    	if(l==r)
    	{
    		tr[k]=a[l];
    		if(a[l]==1||a[l]==0)vis[k]=1;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	updata(k); 
    }
    signed main()
    {
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    	build(1,1,n);
    	for(int i=1,opt,l,c,r;i<=n;i++)
    	{
    		scanf("%lld%lld%lld%lld",&opt,&l,&r,&c);
    		if(l>r)swap(l,r);
    		if(opt==0)
    		{
    			change(1,1,n,l,r);
    		}
    		else
    		{
    			printf("%lld
    ",ask(1,1,n,l,r));
    		}
    	}
    	return 0;
    }

    分块六:

    给出一个长为n的数列,以及n个操作,操作涉及单点插入,单点询问,数据随机生成。

      开一个vector 插入,pair ,

    先说随机数据的情况

    之前提到过,如果我们块内用数组以外的数据结构,能够支持其它不一样的操作,比如此题每块内可以放一个动态的数组,每次插入时先找到位置所在的块,再暴力插入,把块内的其它元素直接向后移动一位,当然用链表也是可以的。

    查询的时候类似,复杂度分析略。

    但是这样做有个问题,如果数据不随机怎么办?

    如果先在一个块有大量单点插入,这个块的大小会大大超过√n,那块内的暴力就没有复杂度保证了。

    还需要引入一个操作:重新分块(重构)

    每根号n次插入后,重新把数列平均分一下块,重构需要的复杂度为O(n),重构的次数为√n,所以重构的复杂度没有问题,而且保证了每个块的大小相对均衡。
    当然,也可以当某个块过大时重构,或者只把这个块分成两半。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<vector>
    #define N 200000
    using namespace std;
    int pos[N],len,le[N],ri[N],n,a[N],st[N],m;
    vector <int> ve[N];
    pair <int,int> query(int b)
    {
    	int x=1;
    	while(b>ve[x].size())
    	{
    		b-=ve[x].size();
    		x++;
    	}
    	return make_pair(x,b-1);
    }
    void rebuild()
    {
    	int top=1;
    	for(int i=1;i<=m;i++)
    	{
    		for(vector<int> ::iterator j=ve[i].begin();j!=ve[i].end();j++)
    		    st[++top]=*j;
    			ve[i].clear();
    	}
    	int le=sqrt(top);
    	for(int i=1;i<=top;i++)ve[(i-1)/le+1].push_back(st[i]);
    	m=(top-1)/le+1;
    }
    void insert(int a,int b)
    {
    	pair <int,int> t=query(a);
    	ve[t.first].insert( ve[t.first].begin() + t.second ,b);
    //	if(ve[t.first].size()>20*len) rebuild();
    }
    int main()
    {
    //	freopen("a9.in","r",stdin);
    //	 freopen("ans.out","w",stdout);
    	scanf("%d",&n);
    	len=sqrt(n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	for(int i=1;i<=n;i++) ve[(i-1)/len+1].push_back(a[i]);
    	int m=(n-1)/len+1;
    	for(int i=1,opt,x,y,c;i<=n;i++)
    	{
    		scanf("%d%d%d%d",&opt,&x,&y,&c);
    		if(opt==0)
    		{
    			insert(x,y);
    		}
    		if(opt==1)
    		{
    			pair <int,int> t = query(y);
    			printf("%d
    ",ve[t.first][t.second]);
    		}
    	}
    	return 0;
    }

    分块七:

    给出一个长为n的数列,以及n个操作,操作涉及区间乘法,区间加法,单点询问。

    很显然,如果只有区间乘法,和分块入门 1 的做法没有本质区别,但要思考如何同时维护两种标记。

    我们让乘法标记的优先级高于加法(如果反过来的话,新的加法标记无法处理)

    若当前的一个块乘以m1后加上a1,这时进行一个乘m2的操作,则原来的标记变成m1*m2,a1*m2

    若当前的一个块乘以m1后加上a1,这时进行一个加a2的操作,则原来的标记变成m1,a1+a2

    #include<map>
    #include<set>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define mod 10007
    #define pi acos(-1)
    #define inf 0x7fffffff
    #define ll long long
    using namespace std;
    ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,blo;
    int v[100005],bl[100005],atag[1005],mtag[1005];
    void reset(int x)
    {
        for(int i=(x-1)*blo+1;i<=min(n,x*blo);i++)
            v[i]=(v[i]*mtag[x]+atag[x])%mod;
        atag[x]=0;mtag[x]=1;
    }
    void solve(int f,int a,int b,int c)
    {
        reset(bl[a]);
        for(int i=a;i<=min(bl[a]*blo,b);i++)
        {
            if(f==0)v[i]+=c;
            else v[i]*=c;
            v[i]%=mod;
        }
        if(bl[a]!=bl[b])
        {
            reset(bl[b]);
            for(int i=(bl[b]-1)*blo+1;i<=b;i++)
            {
                if(f==0)v[i]+=c;
                else v[i]*=c;
                v[i]%=mod;
            }
        }
        for(int i=bl[a]+1;i<=bl[b]-1;i++)
        {
            if(f==0)atag[i]=(atag[i]+c)%mod;
            else 
            {
                atag[i]=(atag[i]*c)%mod;
                mtag[i]=(mtag[i]*c)%mod;
            }
        }
    }
    int main()
    {
        n=read();blo=sqrt(n);
        for(int i=1;i<=n;i++)v[i]=read();
        for(int i=1;i<=n;i++)bl[i]=(i-1)/blo+1;
        for(int i=1;i<=bl[n];i++)mtag[i]=1;        
        for(int i=1;i<=n;i++)
        {
            int f=read(),a=read(),b=read(),c=read();
            if(f==2)printf("%d
    ",(v[b]*mtag[bl[b]]+atag[bl[b]])%mod);
            else solve(f,a,b,c);
        }
        return 0;
    }

    分块八:

    给出一个长为n的数列,以及n个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c。

    区间修改没有什么难度,这题难在区间查询比较奇怪,因为权值种类比较多,似乎没有什么好的维护方法。

    模拟一些数据可以发现,询问后一整段都会被修改,几次询问后数列可能只剩下几段不同的区间了。

    我们思考这样一个暴力,还是分块,维护每个分块是否只有一种权值,区间操作的时候,对于同权值的一个块就O(1)统计答案,否则暴力统计答案,并修改标记,不完整的块也暴力。

    这样看似最差情况每次都会耗费O(n)的时间,但其实可以这样分析:

    假设初始序列都是同一个值,那么查询是O(√n),如果这时进行一个区间操作,它最多破坏首尾2个块的标记,所以只能使后面的询问至多多2个块的暴力时间,所以均摊每次操作复杂度还是O(√n)。

    换句话说,要想让一个操作耗费O(n)的时间,要先花费√n个操作对数列进行修改。

    初始序列不同值,经过类似分析后,就可以放心的暴力啦。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    using namespace std;
    const int N = 1000000;
    int pos[N],le[N],ri[N],cnt,n,a[N],tag[N],len;
    void reset(int x)
    {
    	if(tag[x]==-1)return;
    	else
    	{
    		for(int i=le[x];i<=ri[x];i++)
    		a[i]=tag[x];
    	}
    	tag[x]=-1;
    }
    void change(int l,int r,int c)
    {
    	int ans=0;
    	reset(pos[l]);
    	for(int i=l;i<=min(ri[pos[l]],r);i++)
    	{
    		if(a[i]!=c)a[i]=c;
    		else ans++;
    	}
    	if(pos[l]!=pos[r])
    	{
    		reset(pos[r]);
    		for(int i=le[pos[r]];i<=r;i++)
    		{
    			if(a[i]!=c)a[i]=c;
    			else ans++;
    		}
    	}
    	for(int i=pos[l]+1;i<=pos[r]-1;i++)
    	{
    		if(tag[i]!=-1)
    		{
    			if(tag[i]!=c)tag[i]=c;
    			else ans+=len;
    		}
    		else
    		{
    			for(int j=le[i];j<=ri[i];j++)
    			{
    				if(a[j]!=c)a[j]=c;
    				else ans++;
    				tag[i]=c;
    			}
    		}
    	}
    	printf("%d
    ",ans);
    }
    int main()
    {
    	scanf("%d",&n);
        len=sqrt(n);
    	memset(tag,-1,sizeof(tag));
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(int i=1;i<=n;i++)pos[i]=(i-1)/len+1;
    	for(int i=1;i<=pos[n];i++)
    	{
    		le[i]=(i-1)*len+1;
    		ri[i]=min(n,i*len);
    	}
    	for(int i=1,l,r,c;i<=n;i++)
    	{
    		scanf("%d%d%d",&l,&r,&c);
    		change(l,r,c);
    	}
    	return 0;
    }

    分块九:

    给出一个长为n的数列,以及n个操作,操作涉及询问区间的最小众数。   不带修改,要是带呢?

    #include<map>
    #include<set>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define mod 10007
    #define pi acos(-1)
    #define inf 0x7fffffff
    #define ll long long
    using namespace std;
    ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,blo,id;
    int v[100005],bl[100005];
    int f[605][605];
    map<int,int>mp;
    int val[100005],cnt[100005];
    vector<int>ve[100005];
    void pre(int x)
    {   
        memset(cnt,0,sizeof(cnt));
        int mx=0,ans=0;
        for(int i=(x-1)*blo+1;i<=n;i++)
        {       
            cnt[v[i]]++;        
            int t=bl[i];
            if(cnt[v[i]]>mx||(cnt[v[i]]==mx&&val[v[i]]<val[ans]))
                ans=v[i],mx=cnt[v[i]];
            f[x][t]=ans;
        }
    }
    int query(int l,int r,int x)
    {
        int t=upper_bound(ve[x].begin(),ve[x].end(),r)-lower_bound(ve[x].begin(),ve[x].end(),l);
        return t;
    }
    int query(int a,int b)
    {
        int ans,mx;
        ans=f[bl[a]+1][bl[b]-1];
        mx=query(a,b,ans);
        for(int i=a;i<=min(bl[a]*blo,b);i++)
        {
            int t=query(a,b,v[i]);
            if(t>mx||(t==mx&&val[v[i]]<val[ans]))ans=v[i],mx=t;
        }
        if(bl[a]!=bl[b])
            for(int i=(bl[b]-1)*blo+1;i<=b;i++)
            {
                int t=query(a,b,v[i]);
                if(t>mx||(t==mx&&val[v[i]]<val[ans]))ans=v[i],mx=t;
            }
        return ans;
    }
    int main()
    {
        n=read();
        blo=200;
        for(int i=1;i<=n;i++)
        {
            v[i]=read();
            if(!mp[v[i]])
            {
                mp[v[i]]=++id;
                val[id]=v[i];
            }
            v[i]=mp[v[i]];
            ve[v[i]].push_back(i);
        }
        for(int i=1;i<=n;i++)bl[i]=(i-1)/blo+1;
        for(int i=1;i<=bl[n];i++)pre(i);
        for(int i=1;i<=n;i++)
        {
            int a=read(),b=read();
            if(a>b)swap(a,b);
            printf("%d
    ",val[query(a,b)]);
        }
        return 0;
    }
    

          分块--好爽

  • 相关阅读:
    EF实现增删改查
    托管代码与非托管代码的区别
    堆、栈以及队列
    C#装箱和拆箱
    Leecode刷题之旅-C语言/python-349两个数组的交集
    Leecode刷题之旅-C语言/python-344反转字符串
    Leecode刷题之旅-C语言/python-217存在重复元素
    Leecode刷题之旅-C语言/python-206反转链表
    Leecode刷题之旅-C语言/python-204计数质数
    Leecode刷题之旅-C语言/python-203移除链表元素
  • 原文地址:https://www.cnblogs.com/yelir/p/11559947.html
Copyright © 2011-2022 走看看