简述:

  今天主要讲分治(主要是二分)、倍增、贪心、搜索,还乱入了爬山算法和模拟退火(汗。。。)

一、分(er)治(fen):

  二分是个在OI中广泛运用的思想,随便举些例子,就足以发现二分的运用的广泛性:二分查找、二分答案;归并排序、快速排序;线段树、二叉查找树;0-1线性规划以及经常出现的搭配某个算法的二分题。至于分治,是解决一类可合并问题的法宝。

  对于一道满足二分性的题,我们就可以考虑用二分做它。二分性的实质是存在一个单调性或是临界点:

    单调性:可能的答案在整体或在某一的区间是单调的,就可以对这个区间二分,找到这个区间的最优答案。

     

    临界点:答案的可行性在某一点突然发生突变,即把所有可能的答案画作一条线段的话,会明显发现以一个点为界限,左边的数据都可行,而右边都不可行。而那个界限一般就是我们要找的最优化问题的解。所以二分答案的实质也是用二分的方法找一个界限。

  

  二分通过每次处理都把要处理的有序区间缩小一半,达到了迅速的O(log n)的复杂度,并将最优化问题转化为判定性问题,再配合其他的一些算法,为很多最优化问题的解增添了一份可能。事实上,有些文字能让人意识到某道题可以二分(要对这些文字敏感,有些题说的没这么直接,要能看出来):

      最大值最小;

      最小值最大;

      有序;

      分数;

      时间复杂度;

      ……

有时遇到一些看起来像是二分的题目,可以先打个表看一下是否满足二分性。

  一个简单的模板:

 

  (judge函数为判定当前枚举的界限mid能否可行。如果可行的话说明mid有可能就是最终的答案,同时也有可能有更优的答案,别忘记录一下)

来看到简单的题:

(入门题…)看到了“最大值最小”,要敏感哦。

  二分最小的最大值mid,接着用贪心扫一遍判定一下能否分成最大值小于mid的m(m<=M)段就行了。

  直接求可能有些难度,但看到“请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间”,这不就是“最大值最小”的另一种说法吗?,所以还是要对二分的关键词敏锐些!考虑二分答案,二分最小的最大值,从后往前扫一遍用贪心判定就行了。  

二分的一般思路即为:确定要二分——要二分什么——判定什么——怎么判定(用什么算法)。

  一个最优化问题,可以考虑一下二分。显然要二分能组成的套牌数mid,判定能否用当下的牌组成这么多的套牌。记录每种牌到mid不足量的和sum。显然每种牌的不足都要靠joker来补足。首先发现每套牌最多只能有一个joker,所以sum应<=mid,否则判定结果为false;还发现joker最多只有m张,所以sum应<=m,否则判定结果为false。只要上面两个条件都满足,我们就可以用当下牌组成每套牌最多只有1个joker的mid套牌。

  放在U盘中的文件的最大l即为接口大小+“最小需要多大的接口”=最大值最小!考虑二分答案。二分最小的接口大小mid,把文件按大小从小到大排个序,将所有大小小于mid的物品做一个01背包,看看能否满足最大总价值不小于p即可。

  可先跑一遍广搜判断有无解以及从1到n的最少经过几个电话线杆以得知能否直接被电信公司报销全部费用。如不有解且不能报销全部费用的话,再更深地思考一下。又发现了“最大值最小”这一主题,再考虑二分。二分总费用mid(因超过k条而不被电信公司免费的最长的电话线长度),此时长度小于等于mid的电话线可以尽情搭,而大于mid的电话线则全让电信公司给免费(若小于k条的话),故可以把所有边权<=mid的边的边权都修改为0,大于mid的都修改为1,跑一遍最短路(边权只有01的最短路可用双端队列的广搜实现)。若得到的最短路径长度len<k,则说明电信公司还可再多给免费几条电话线,mid还有可能更小,记录答案后在r=mid-1;若len==k,说明刚好把需要的能免费的电话线都免费了,输出mid即可;若len>k,说明“免费超额”了,要把mid改大点,即l=mid+1。

讲点有趣的东西吧。如何生成一个最优比率生成树?

  

二分的一个十分优雅又不失尴尬的考法(。。。),这也是为什么碰到分数可以考虑二分的原因。以最大为例,设最终答案为ans,则所有大于ans的可能答案都不会有一个生成树满足条件,而小于ans的可能答案总会被一个生成树的答案大于,发现ans即为一个界限,可以用二分。这里二分答案k,即要判定是否存在一个生成树使∑(benifit[i])/∑(cost[i])>=k,让k尽可能大、尽可能去接近最终答案就好了。

      由于具有重大的现实意义,不妨假设cost都大于0。

      则∑(benifit[i])>=k*∑(cost[i]);

      再变一下:k*∑(cost[i])-∑(benifit[i])<=0;

        ∑(k*cost[i])-∑(benifit[i])<=0;

        ∑(k*cost[i]-benifit[i])<=0;

 看到这里是不是就懂了?只要我们再把所有边的边权变为k*cost[i]-benifit[i],再跑一遍最小生成树,把权值之和与0比较,若<=0则判定为true,否则为false。

 以后对于类似的分数最优化,都可以用类似的变形随便变变,尝试用二分做。

  平均乐趣值最大,实际上就相当于总收入/总花费最大。

  小技巧:对于一个既有边权又有点权的有向图,我们可以把点权挪到边权上去。因为我们一旦踏上某条边,这条边的终点我们一定也会经过。而对于这道题来说,尽管每个点的点权只能被加一次,可是考虑一下八字形的情况(即有点重复经过多次的代表),这种情况实质上是由多个环组成的情况。由于题目要求的分数是一种平均数,易知组成那个八字形的两个环中一定有一个环的   一定。故这题又是分数规划,思路跟楼上非常像,不过最优比率生成树变成了最优比率环而已。而对于判是否有环的权值和为负(为0的情况不管也没什么啦),这不就是判负权回路吗?bellman-ford与spfa任君选择。。。

  关于bellman-ford以及进阶的spfa,您可以看看作者的另一篇博客:Bellman-ford算法与SPFA算法思想详解及判负权环(负权回路)

二、倍增:

  跟二进制有着密切的不可告人的联系,看见二进制及2的k次方,想想倍增准没错!

  常用于快速幂、快速乘(明明一点都不快)、快速矩阵乘法(主要还是矩阵快速幂)、倍增求...(LCA出现居多)。

  1、快速幂:我们算a的b次方模p的值。一般是O(n)算法乘一波,当b特别大时显然不行。考虑将B二进制分解,就可O(log n)算出结果。

  2、快速乘:

  

  这就没了??(心里一句***)

  果然关键时刻还得靠大佬:O(1)快速乘 - 紫芝的博客 - CSDN博客

  3、矩阵乘法:用于求一类常系数递推方程,这也是矩阵乘法的一个主要用途了。简单的说,对于一个一次的常系数递推方程(如f(n)=7*f(n-1)+2*f(n-2)+5)(目前只会这个QAQ)计算f(n),一般算法都是O(n)的递推,但当n特别大时肿么办?

  我们竖着写一个m*1的矩阵a,第i行分别为方程中去掉系数的第i项,如果为常数则写为1(比如这里的an-1的三项从上往下分别为f(n-1),f(n-2),1)。都知道矩阵乘法是一个n*k的矩阵乘一个k*m的矩阵得到一个n*m的矩阵,而矩阵乘法不满足交换律,但满足结合律和左右分配率律。只要我们在矩阵a左边写一个矩阵j(称为转换矩阵),要求j*a能得到下一个a(即f(n),f(n-1),1),从最开始的a0开始,每被j乘一次ai就变成ai+1,由矩阵的结合律可知,只要算出j的n次方(用快速幂,若要取模,直接对矩阵每一项取模就行)后再与a0相乘得到an,答案就为an的第一项。时间复杂度从O(n)进化为O(log n)。

  4、倍增求LCA:快速地(O(log n))求树上的最近公共祖先,以迅速处理树上的路径问题(dis(u,v)=dis(u,root)+dis(v,root)-2*dis(lca(u,v))。

看题喽!:

  转换矩阵为:

      1 1

      1 0

 

  如果对于每一支军队都做一遍所有指令后再看下一个军队,显然会超时。为什么?是不是我们看待军队的角度不对?如果我们把军队i写作一个矩阵:

  

xi
yi
1(有常数参与矩阵乘法时常常需要个1)

  同时对于三种操作,也可以写出相应的矩阵:  

  操作1:

1 0 p
0 1 q
0 0 1

  操作2:

-1 0 0
0 1 0
0 0 1

  操作3:

1 0 0
0 -1 0
0 0 1

  因为所有军队收到的命令相同,又有矩阵乘法的结合性,故可将所有操作矩阵乘起来得到一个结果矩阵,在用这个结果矩阵分别去乘每一个军队对应的矩阵就得到答案了。时间复杂度O(n+m)。

矩阵的另一个大用途就是把一堆让人头疼的东西抽象化。只要抽象化成一个数学结构,问题一般就好解了。

  显然可以用递推方程做,但发现方程不好写。为什么不好写?主要还是因为对不同范围的数,对应的方程和转换矩阵也不太一样。先不要放弃,分段考虑尝试一下,惊奇地发现转移矩阵竟可以用一种方法表示出来:

  

只要看到异或,我们就应该想到一个数异或自己等于0(凭此据说可以用三次异或来交换整形变量),一个数异或0仍等于它自己,且异或满足交换律、结合律与分配律。类比求树上两点间的路径长度dis(u,v)=dis(u,root)+dis(v,root)-2*dis(lca(u,v),不过在这里设dis(u,v)为两点间路径上所有边权的异或值。发现公式改成dis(u,v)=dis(u,root)+dis(v,root)就行了!因为dis(u,root)+dis(v,root)相较于dis(u,v)只多了2个dis(lca,root),然而dis(lca,root)异或下自己就等于0了,所以最终结果仍是dis(u,v)。所以只要处理出每个点到根root的路径上所有边权的异或值就行了。

  容易知道选的点一定是三个点的两两LCA的其中一个。直接求三遍lca到三点的距离,去最小值就好了。

三、贪心

  

  贪心策略的证明:枚举所有情况,都不会比它更优了。

  

  非常简单的贪心:先合小的。搞一个小根堆就好了。

  //(dms正解:维护哈夫曼树???)

    插入哈夫曼树的有关知识:

      

    (原博客:https://www.cnblogs.com/dalt/p/8001560.html  代码为不严格的伪代码,只求明义。满二叉树的定义遵循国外(国际)定义)

    我们画一棵每个非叶节点都有两个子节点的二叉树,以叶节点表示起始所有的石子,每两个兄弟节点连向同一个父亲节点即视为一次合并,发现此二叉树在哈夫曼树定义下的权值即为答案,故要答案最小的话,维护一颗哈夫曼树就好了。

  由于出现的字母固定,首先想到了字典树,两两互不为前缀,即要求用字典树的每个叶节点代表单词,可在所有叶节点记录下某个单词出现的次数,那么这个字典树在哈夫曼树定义下的权重就是整个文章的长度了。由此想到了哈夫曼树,不过在这里是K叉的特殊情况。

  看看K叉哈夫曼树对于二叉哈夫曼树在上面的命题中有什么变化:

    对于命题1,显然这个K叉哈夫曼树不一定是满K叉树了,不过能证得所有非叶节点最少有2个儿子(虽然没什么用)。

    命题2仍然成立。

    命题3则强化为在满k叉树的情况下最小的k个节点连向同一个父亲f(满k叉树的情况下,若深度浅的地方有点属于前k小的点(不考虑相等的情况,若相等的话可随便,不会影响结果),必有一点x比他大且为f的儿子,把它与x交换,能得到权值更小的树)。

  由构造二叉哈夫曼树的方法联想到构造k叉哈夫曼树的方法:可以每次都将当前k个最小的拿出来、连到同一个父节点上再把那个新建的父节点放回堆里。但这样做会有一个明显的错误:如果最后一次从堆取出的节点少于k个,就会导致根结点的儿子数少于k个。这样的话就可以从孙子一辈(如果有孙子的话)随便拿来个点连根上,使整棵树的权值减小,故不是合法的哈夫曼树。

  按上文“错误”的方法来看,每次我们都从堆里取出k个点,放回1个点,相当于取出(k-1)个点,最后要剩下一个点作为哈夫曼树的根。若最后一次取出的节点正好为k,则整棵哈夫曼树为满k叉树,不会出现上文的那个明显的错误。这时我们从堆里取出了很多次(k-1)个点,堆里还剩1个点,一共有n个点,故(n-1)mod (k-1)=0 ,即(n-1)为(k-1)的倍数。那么当(n-1)为(k-1)的倍数,即构造的哈夫曼树为满K叉树时可以吗?

  可以按照证二叉情况的相似思路证明:

    通过归纳法说明,当只有一个顶点或只有k个及以内的节点时,算法显然正确。当顶点数少于m时,若上述算法都可以构建一株合理的哈夫曼树。那么当我们持有m个结点组成的结点集合V时,由于命题三知权重最小的k个结点组成的节点集合A可以有相同的父亲f,我们利用上述方法,使用m-(k-1)个结点组成的结点集合V'(V中移除了A 后加入f得到)建立对应的一株哈夫曼树F。假设T为V的哈夫曼树。我们可以在T的基础上建立一株新树T',其中T'与T的区别在于我们为f赋予权值A.w,同时从T中删除A,显然T'.w = T.w -A.w。而T'也是满足以V'为叶结点的一株二叉树,故知F.w<=T'.w=T.w-A.w。同样我们可以在F的基础上建立另外一株二叉树F',其中F'与F的区别在于我们移除f结点的权值,并为其添加A,此时显然有F'.w=F.w+A.w,而由于F'.w是V的一株二叉树,因此T.w<=F'.w=F.w+A.w。结合两条不等式可以得出F.w+A.w=T.w,即在F的基础上做改变得到的树F'是V的哈夫曼树。因此我们可以通过递归的思路建立哈夫曼树。

  对于哈夫曼树不为满k叉树的情况怎么办呢?我们可以加一些“零点”(即点权为0的点),这样并不会影响到整棵树的权值。在n个点的基础上加上几个零点得到n'个点使(n'-1)为(k-1)的倍数,这样又可以转化为满k叉树的情况做了。

  最后在考虑怎样让最长的si最短。显然能看出由于儿子顺序、相同值节点顺序的不确定性,哈夫曼树不是唯一的,这导致可能会在最后一问栽跟头。其实可以用贪心解决,对于权值相同的节点,深度小的优先选择,这样就能保证最后最长的si最短了。

 

  若图中两点间存在一条各边边权都小于m的路径,则在最大生成树上两点间的唯一路径也符合各边边权小于m。可以这样理解:若图的最大生成树上有一条边的边权小于m,删去这条边会将树分割成2个连通块A和B,由于该边是连通块A到连通块B的最大边(参见这里的判断),故连通块A的所有点到连通块B的所有点的所有路径必有一条边边权小于m,即最大生成树上两点间没有合法路径,在整个图上这两点间也不会有合法路径。若图上有合法路径,则最大生成树上一定有。

  对于两点间路径中最小边权的最大值则可用倍增实现。对于有列车站的点,我们可以将它们用非常大的边(近似无穷大)连成一个连通块(这里用了最简单的环)(相当于不受重量限制的一种表现形式),最后模拟即可。

上个AC代码吧:

  

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath> using namespace std; const int MAXN=,MAXDIS=; long long ans,ord[MAXN+];//ord存单子 long long lim[MAXN+];//每个城市的交易限制 char ch; bool fu; inline long long getint()//这里应该是getlonglong,后来懒得改了
{
ans=;
ch=getchar();
fu=;
while(!isdigit(ch)) fu|=(ch=='-'),ch=getchar();
while(isdigit(ch)) ans=(ans<<)+(ans<<)+(ch^),ch=getchar();
return fu?-ans:ans;
} int n,m,Q,lst[MAXN+],to[MAXN<<],nxt[MAXN<<],cnt;//边的限制 long long dis[MAXN<<]; long long db[][MAXN+],leth[MAXN+]; inline void addedge(int u,int v,long long w)
{
nxt[++cnt]=lst[u];
lst[u]=cnt;
to[cnt]=v;
dis[cnt]=w;
} bool vis[MAXN+]; struct node{
int hao;
long long len;
}head; inline bool operator < (const node &a,const node &b)
{
return a.len<b.len;
} priority_queue<node> q; int fa[][MAXN+],dep[MAXN+]; #define min(a,b) ((a)<(b)?(a):(b)) inline int Log2(int a)
{
return log(a)/log();
} inline void Prim()//最大生成树(要建树)
{
memset(leth,,sizeof leth);
leth[]=;
int ok=,t,too,f,lo,d;
q.push((node){,});
fa[][]=;
dep[]=-;
while(ok<n)
{
head=q.top();
q.pop();
if(vis[t=head.hao]) continue;
vis[t]=;
f=fa[][t];
d=dep[t]=dep[f]+;
if(t!=)
{
lo=Log2(d);
for(int i=;i<=lo;++i)
{
fa[i][t]=fa[i-][fa[i-][t]];
db[i][t]=min(db[i-][t],db[i-][fa[i-][t]]);
}
}
++ok;
for(int e=lst[t];e;e=nxt[e])
{
too=to[e];
if(vis[too]==&&leth[too]<dis[e])
{
leth[too]=dis[e];
fa[][too]=t;
db[][too]=dis[e];
q.push((node){too,dis[e]});
}
}
}
} #define max(a,b) ((a)>(b)?(a):(b))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) inline long long lca(int x,int y)//倍增求最大的最小边权
{
if(x==y) return 0x7ffffffff;
if(dep[x]<dep[y]) swap(x,y);
int lo;
ans=0x7ffffffff;
if(dep[x]>dep[y])
{
lo=Log2(dep[x]-dep[y]);
for(int i=lo;i>=;i--)
if(dep[fa[i][x]]>=dep[y])
{
ans=min(ans,db[i][x]);
x=fa[i][x];
}
}
if(x==y) return ans;
lo=Log2(dep[x]);
for(int i=lo;i>=;i--)
if(fa[i][x]!=fa[i][y])
{
ans=min(ans,db[i][x]);
x=fa[i][x];
ans=min(ans,db[i][y]);
y=fa[i][y];
}
ans=min(ans,db[][x]);
ans=min(ans,db[][y]);
return ans;
} inline void MONI()
{
int now,thenxt;
long long ag,xian;
if(!n) return;
now=ord[];
ag=max(,lim[now]);
if(lim[now]<)
{
putchar('');putchar('\n');
}
for(int i=;i<=n;++i)
{
thenxt=ord[i];
xian=lca(now,thenxt);
ag=min(ag,xian);
if(lim[thenxt]>)
ag=ag+lim[thenxt];
else
{
xian=min(ag,-lim[thenxt]);
ag-=xian;
printf("%lld\n",xian);
}
now=thenxt;
}
} int main()
{
n=getint(),m=getint(),Q=getint();
for(int i=;i<=n;++i) ord[i]=getint();
for(int i=;i<=n;++i) lim[i]=getint();
int u,v;
long long w;
for(int i=;i<=m;i++)
{
u=getint(),v=getint(),w=getint();
addedge(u,v,w);
addedge(v,u,w);
}
int fir=,now=;
if(Q)
fir=now=getint();
for(int i=;i<=Q;++i)
{
v=getint();
addedge(now,v,0x7ffffffff);
addedge(v,now,0x7ffffffff);
now=v;
}
if(now!=fir) //不要忘了要把链接成环
{
addedge(now,fir,0x7ffffffff);
addedge(fir,now,0x7ffffffff);
}
Prim();
MONI();
return ;
}

AC代码(巨长慎点)

四、搜索

  1、基础——枚举:将所有可能需要的情况列出来求解题的算法。一般复杂度都很高(除了一些巧妙/高级的枚举)。

  例子:用不断求下个排列的函数next_pernutation生成全排列

     枚举子集

EX.1、爬山算法

EX.2、模拟退火

继续看搜索

清北学堂算法&&数据结构DAY1——知识整理的更多相关文章

  1. 清北学堂学习总结 day1 数据结构 练习

    1.二叉搜索树 STL set直接做就可以了 2.树状数组+差分数列: codevs 1081 线段树练习 2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Maste ...

  2. 清北学堂寒假集训DAY1

    第一天,上午讲了些基本的技巧和简单算法,主要就是适应这里. 中午跑到食堂吃了顿“饭”(我并没有挖苦233333),然后回宿舍休息休息 因为 迎接我们的是模拟啊啊啊啊啊阿 下午题一发下来,并没有想象中的 ...

  3. 清北学堂学习总结day1

    上午篇 一.高精度计算: [以下内容先只考虑非负数情况] •高精度加法: 思路:[模拟竖式运算] 注意:[进位] •高精度减法: 思路:[同加法类似,模拟竖式运算,进位变退位] 注意: [结果为负数的 ...

  4. 清明培训 清北学堂 DAY1

    今天是李昊老师的讲授~~ 总结了一下今天的内容: 1.高精度算法 (1)   高精度加法 思路:模拟竖式运算 注意:进位 优化:压位 程序代码: #include<iostream>#in ...

  5. 7月清北学堂培训 Day 3

    今天是丁明朔老师的讲授~ 数据结构 绪论 下面是天天见的: 栈,队列: 堆: 并查集: 树状数组: 线段树: 平衡树: 下面是不常见的: 主席树: 树链剖分: 树套树: 下面是清北学堂课程表里的: S ...

  6. 济南清北学堂游记 Day 1.

    快住手!这根本不是暴力! 刷了一整天的题就是了..上午三道题的画风还算挺正常,估计是第一天,给点水题做做算了.. rqy大佬AK了上午的比赛! 当时我t2暴力写挂,还以为需要用啥奇怪的算法,后来发现, ...

  7. 清北学堂2017NOIP冬令营入学测试P4745 B’s problem(b)

    清北学堂2017NOIP冬令营入学测试 P4745 B's problem(b) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 题目描 ...

  8. 清北学堂2017NOIP冬令营入学测试 P4744 A’s problem(a)

    清北学堂2017NOIP冬令营入学测试 P4744 A's problem(a) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试题,每三天结算 ...

  9. 清北学堂 2020 国庆J2考前综合强化 Day2

    目录 1. 题目 T1 一 题目描述 Sol T2 二 题目描述 Sol T3 三 题目描述 Sol T4 四 题目描述 Sol 2. 算法 -- 数据结构 1. 题目 T1 一 题目描述 问题描述 ...

随机推荐

  1. 2.nginx配置详细说明

    Nginx配置详解 nginx概述 nginx是一款自由的.开源的.高性能的HTTP服务器和反向代理服务器:同时也是一个IMAP.POP3.SMTP代理服务器:nginx可以作为一个HTTP服务器进行 ...

  2. 深入理解java:1.1. 类加载器

    从java的动态性到类加载机制   我们知道,Java是一种动态语言. 那么怎样理解这个“动态”呢? 或者说一门语言具备了什么特性,才能称之为动态语言呢? 对于java,我是这样理解的. 我们都知道J ...

  3. vue组件事件(极客时间Vue视频笔记)

    vue组件核心:事件 <body> <div class="app"> <todo-list></todo-list> {{mess ...

  4. [Vim] 01 凡人操作

    历史评价 编辑器之神 一个凡人的自我修养 成神是不可能成神的,只能是先入个门,然后一点一点学 Vim 官网 三种模式 插入模式(注意看光标) 命令模式(注意看光标) 编辑模式(注意看光标) 其实还有一 ...

  5. PHP7中的数据类型(一)计数引用、写时复制,可垃圾回收

    列个简单的表格说明一下:

  6. Linux环境安装mongodb

    介绍 上篇介绍了Linux环境下安装Node.js的步骤,紧接着来安装mongodb.另外,推荐我的另一篇 Windows下图文详解Mongodb安装及配置,先在Windows下熟悉下mongodb, ...

  7. RabbitMq学习3-工作队列(Work queues)

    工作队列(又称:任务队列——Task Queues)是为了避免等待一些占用大量资源.时间的操作.当我们把任务(Task)当作消息发送到队列中,一个运行在后台的工作者(worker)进程就会取出任务然后 ...

  8. gp指标信息

    RSI: 相对强弱指数,RSI的原理简单来说是以数字计算的方法求出买卖双方的力量对比 强弱指标理论认为,任何市价的大涨或大跌,均在0-100之间变动,根据常态分配 认为RSI值多在30-70之间变动, ...

  9. 表单提交 multipart/form-data 和 x-www-form-urlencoded的区别

    表单提交表单有两种提交方式,POST和GET.通常我们会使用POST方式,一是因为形式上的安全 :二是可以上传文件. 我之前经常忽略掉表单的编码类型,觉得它特别长比较难记,而且不设置也似乎不影响什么. ...

  10. 原生js格式化json和格式化xml的方法

    在工作中一直看各位前辈的博客解决各种问题,对我的帮助很大,非常感谢! 之前一直比较忙没有写博客,终于过年有了点空闲时间,可以把自己积累的东西分享下,笔记中的部分函数不是自己写的,都是工作中一点点积累的 ...