1. 程式人生 > >if(true){ I love it }

if(true){ I love it }

轉載地址:https://my.oschina.net/elain/blog/382494

一、什麼是 AOP

AOP(Aspect-OrientedProgramming,面向切面程式設計),可以說是OOP(Object-Oriented Programing,面向物件程式設計)的補充和完善。OOP引入封裝、繼承和多型性等概念來建立一種物件層次結構,用以模擬公共行為的一個集合。當我們需要為分散的物件引入公共行為(日誌、安全、事務)的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌程式碼往往水平地散佈在所有物件層次中,而與它所散佈到的物件的核心功能毫無關係。對於其他型別的程式碼,如安全性、異常處理和透明的持續性也是如此。這種散佈在各處的無關的程式碼被稱為橫切(cross-cutting)程式碼,在OOP設計中,它導致了大量程式碼的重複,模組間的藕合度高,而不利於各個模組的重用。

而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即切面。所謂“切面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組間的耦合度,有利於未來的可操作性和可維護性。AOP代表的是一個橫向的關係,如果說“物件”是一個空心的圓柱體,其中封裝的是物件的屬性和行為;那麼面向方面程式設計的方法,就彷彿一把利刃,將這些空心圓柱體剖開,以獲得其內部的訊息。而剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡。

使用“橫切”技術,AOP把軟體系統分為兩個部分:核心業務邏輯元件和橫切關注點。橫切關注點模組化為特殊的類,這些類被稱為“切面”,好處:1.橫切關注點都集中於一塊,不會出現大量重複程式碼;2.核心模組只關注核心功能的程式碼,模組間藕合度降低。

二、AOP 的實現原理

<img src="AOP代理.jpg" />

如圖:AOP 實際上是由目標類的代理類實現的AOP 代理其實是由 AOP 框架動態生成的一個物件,該物件可作為目標物件使用。AOP 代理包含了目標物件的全部方法,但 AOP 代理中的方法與目標物件的方法存在差異,AOP 方法在特定切入點添加了增強處理,並回調了目標物件的方法

三、AOP相關概念

連線點(Joinpoint

:在程式執行過程中某個特定的點,比如某方法呼叫的時候或者處理異常的時候。在Spring AOP中,一個連線點總是表示一個方法的執行。通俗的說就是加入切點的那個點

通知(Advice:在切面的某個特定的連線點上執行的動作。其中包括了“around”“before”“after”等不同型別的通知(通知的型別將在後面部分進行討論)。許多AOP框架(包括Spring)都是以攔截器做通知模型,並維護一個以連線點為中心的攔截器鏈。

切入點(Pointcut:匹配連線點的斷言。通知和一個切入點表示式關聯,並在滿足這個切入點的連線點上執行(例如,當執行某個特定名稱的方法時)。切入點表示式如何和連線點匹配是AOP的核心:Spring預設使用AspectJ切入點語法。

引入(Introduction:用來給一個型別宣告額外的方法或屬性(也被稱為連線型別宣告(inter-type declaration))。Spring允許引入新的介面(以及一個對應的實現)到任何被代理的物件。例如,你可以使用引入來使一個bean實現IsModified介面,以便簡化快取機制。

織入(Weaving:將切面應用到目標物件來建立新的代理物件的過程。這些可以在編譯時(例如使用AspectJ編譯器),類載入時和執行時完成。Spring和其他純Java AOP框架一樣,在執行時完成織入。

增強(Advice):是織入到目標類連線點上的一段程式程式碼。Spring使用增強類定義橫切邏輯,同時由於Spring只支援方法連線點,增強還包括了在方法上的哪一點加入橫切程式碼的方位資訊,所以增強既包括橫切邏輯、還包含部分連線點的資訊。

引介(Introduction):是一種特殊的增強,為類新增一些屬性和方法。

切面(Advisor):代表一般切面,包含了橫切程式碼和連線點資訊,本身是一個簡單的切面,橫切的連線點是目標類的所有方法。3種類型:一般切面(advisor)、切點切面(PointcutAdvisor)、引介切面(IntroductionAdvisor)。

四、Spring中AOP的實現

第一種是基於xml配置檔案方式的實現,

第二種是基於註解方式的實現。

首先我們來看一下業務邏輯service層:

/** 
 * RegisterService的實現類 
 * @author 曹勝歡 */  
public class RegisterServiceImpl implements RegisterService {  
    private  RegisterDao registerDao;  
    public RegisterServiceImpl() {}  
    /** 帶引數的構造方法 */  
    public RegisterServiceImpl(RegisterDao  registerDao){  
        this.registerDao =registerDao;  
    }  
    public void save(String loginname, String password) {  
        registerDao.save(loginname, password);  
        throw new RuntimeException("故意丟擲一個異常。。。。");  
    }  
      /** set方法 */  
    public void setRegisterDao(RegisterDao registerDao) {  
        this.registerDao = registerDao;  
}}

對於業務系統來說,RegisterServiceImpl類就是目標實現類,它的業務方法,如save()方法的前後或程式碼會出現異常的地方都是AOP的連線點。

下面是日誌服務類的程式碼:

/** 
 * 日誌切面類 
 * @author 曹勝歡 
 */  
public class LogAspect {  
    //任何通知方法都可以將第一個引數定義為 org.aspectj.lang.JoinPoint型別   
    public void before(JoinPoint call) {  
        //獲取目標物件對應的類名  
        String className = call.getTarget().getClass().getName();  
        //獲取目標物件上正在執行的方法名  
        String methodName = call.getSignature().getName();  
        System.out.println("前置通知:" + className + "類的" + methodName + "方法開始了");  
    }  
    public void afterReturn() {  
        System.out.println("後置通知:方法正常結束了");  
    }  
    public void after(){  
        System.out.println("最終通知:不管方法有沒有正常執行完成,一定會返回的");  
    }  
    public void afterThrowing() {  
        System.out.println("異常丟擲後通知:方法執行時出異常了");  
    }  
    //用來做環繞通知的方法可以第一個引數定義為org.aspectj.lang.ProceedingJoinPoint型別  
    public Object doAround(ProceedingJoinPoint call) throws Throwable {  
        Object result = null;  
        this.before(call);//相當於前置通知  
        try {  
            result = call.proceed();  
            this.afterReturn(); //相當於後置通知  
        } catch (Throwable e) {  
            this.afterThrowing();  //相當於異常丟擲後通知  
            throw e;  
        }finally{  
            this.after();  //相當於最終通知  
        }  
        return result;  
    }  
}

這個類屬於業務服務類,如果用AOP的術語來說,它就是一個切面類,它定義了許多通知。Before()、afterReturn()、after()和afterThrowing()這些方法都是通知。

下面我們就來看具體配置,首先來看一下:

<1>.基於xml配置檔案的AOP實現:這種方式在實現AOP時,有4個步驟

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>  
    <bean id="registerDaoImpl" class="com.zxf.dao.RegisterDaoImpl"/>  
    <bean id="registerService" class="com.zxf.service.RegisterServiceImpl">  
        <property name=" registerDaoImpl " ref=" RegisterDaoImpl "/>  
    </bean>  
    <!-- 日誌切面類 -->  
    <bean id="logAspectBean" class="com.zxf.aspect.LogAspect"/>  
    <!-- 第1步: AOP的配置 -->  
    <aop:config>  
        <!-- 第2步:配置一個切面 -->  
        <aop:aspect id="logAspect" ref="logAspectBean">  
            <!-- 第3步:定義切入點,指定切入點表示式 -->  
            <aop:pointcut id="allMethod"   
                expression="execution(* com.zxf.service.*.*(..))"/>   
            <!-- 第4步:應用前置通知 -->  
            <aop:before method="before" pointcut-ref="allMethod" />  
            <!-- 第4步:應用後置通知 -->  
            <aop:after-returning method="afterReturn" pointcut-ref="allMethod"/>  
            <!-- 第4步:應用最終通知 -->  
            <aop:after method="after" pointcut-ref="allMethod"/>  
            <!-- 第4步:應用丟擲異常後通知 -->  
            <aop:after-throwing method="afterThrowing" pointcut-ref="allMethod"/>  
            <!-- 第4步:應用環繞通知 -->  
            <!--  
            <aop:around method="doAround" pointcut-ref="allMethod" /> 
             -->  
        </aop:aspect>  
    </aop:config>  
</beans>

上述配置針對切入點應用了前置、後置、最終,以及丟擲異常後通知。這樣在測試執行RegisterServiceImpl類的save()方法時,控制檯會有如下結果輸出:

前置通知:com.zxf.service.RegisterServiceImpl類的save方法開始了。

針對MySQL的RegisterDao實現中的save()方法。

後置通知:方法正常結束了。

最終通知:不管方法有沒有正常執行完成,一定會返回的。

下面我們在來看一下第二種配置方式:

<2>基於註解的AOP的實現

     首先建立一個用來作為切面的類LogAnnotationAspect,同時把這個類配置在spring的配置檔案中。

        在spring2.0以後引入了JDK5.0的註解Annotation的支援,提供了對AspectJ基於註解的切面的支援,從而 更進一步地簡化AOP的配置。具體的步驟有兩步。

Spring的配置檔案是如下的配置:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>  
    <bean id="registerDao" class="com.zxf.dao.RegisterDaoImpl"/>  
    <bean id="registerService" class="com.zxf.service.RegisterServiceImpl">  
        <property name="registerDao" ref="registerDao"/>  
    </bean>  
    <!-- 把切面類交由Spring容器來管理 -->  
    <bean id="logAspectBean" class="com.zxf.aspect.LogAnnotationAspect"/>  
    <!-- 啟用spring對AspectJ註解的支援 -->  
    <aop:aspectj-autoproxy/>  
</beans>

這是那個切面的類LogAnnotationAspect

/** 
 * 日誌切面類 
 */  
@Aspect  //定義切面類  
public class LogAnnotationAspect {  
    @SuppressWarnings("unused")  
    //定義切入點,提供一個方法,這個方法的名字就是改切入點的id  
    @Pointcut("execution(* com.zxf.service.*.*(..))")  
    private void allMethod(){}  
    //針對指定的切入點表示式選擇的切入點應用前置通知  
    @Before("execution(* com. zxf.service.*.*(..))")  
    public void before(JoinPoint call) {  
        String className = call.getTarget().getClass().getName();  
        String methodName = call.getSignature().getName();  
        System.out.println("【註解-前置通知】:" + className + "類的"   
                + methodName + "方法開始了");  
    }  
    //訪問命名切入點來應用後置通知  
    @AfterReturning("allMethod()")  
    public void afterReturn() {  
        System.out.println("【註解-後置通知】:方法正常結束了");  
    }  
    //應用最終通知  
    @After("allMethod()")  
    public void after(){  
        System.out.println("【註解-最終通知】:不管方法有沒有正常執行完成,"   
                + "一定會返回的");  
    }  
    //應用異常丟擲後通知  
    @AfterThrowing("allMethod()")  
    public void afterThrowing() {  
        System.out.println("【註解-異常丟擲後通知】:方法執行時出異常了");  
    }  
    //應用周圍通知  
    //@Around("allMethod()")  
    public Object doAround(ProceedingJoinPoint call) throws Throwable{  
        Object result = null;  
        this.before(call);//相當於前置通知  
        try {  
            result = call.proceed();  
            this.afterReturn(); //相當於後置通知  
        } catch (Throwable e) {  
            this.afterThrowing();  //相當於異常丟擲後通知  
            throw e;  
        }finally{  
            this.after();  //相當於最終通知  
        }  
        return result;  
    }  
}

五:Spring中AOP的兩種代理方式(Java動態代理和CGLIB代理)

Spring AOP使用動態代理技術在執行期織入增強程式碼。使用兩種代理機制:基於JDK的動態代理(JDK本身只提供介面的代理);基於CGlib的動態代理

1. JDK的動態代理主要涉及java.lang.reflect包中的兩個類:Proxy和InvocationHandler。其中InvocationHandler只是一個介面,可以通過實現該介面定義橫切邏輯,並通過反射機制呼叫目標類的程式碼,動態的將橫切邏輯與業務邏輯織在一起。而Proxy利用InvocationHandler動態建立一個符合某一介面的例項,生成目標類的代理物件。(只能為介面建立代理例項)

//需要被代理的介面
public interface ForumService {
	public void removeTopic(int topicId);
	public void removeForum(int forumId);
}

//被代理介面的實現類,包含核心的業務邏輯
public class ForumServiceImpl implements ForumService{
	@Override
	public void removeTopic(int topicId) {
		System.out.println("模擬刪除Topic記錄:"+ topicId);
		try {
			Thread.currentThread().sleep(20);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void removeForum(int forumId) {
		System.out.println("模擬刪除Forum記錄:"+ forumId);
		try {
			Thread.currentThread().sleep(40);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}
//效能監控核心程式碼生成
public class MethodPerformance {
	private long begin;
	private long end;
	private String serviceMethod;
	
	public MethodPerformance(String serviceMethod) {
		this.serviceMethod = serviceMethod;
		this.begin = System.currentTimeMillis();
	};
	
	public void printPerformance(){
		this.end = System.currentTimeMillis();
		long elapse = this.end - this.begin;
		System.out.println(serviceMethod + " cost " + elapse +"ms");
	}
}

//執行緒安全的橫切邏輯
public class PerformanceMonitor {
	private static ThreadLocal<MethodPerformance> tl= new ThreadLocal<MethodPerformance>();
	
	public static void begin(String method){
		System.out.println("begin monitor");
		MethodPerformance mp = new MethodPerformance(method);
		tl.set(mp);
	}
	
	public static void end(){
		System.out.println("end monitor");
		MethodPerformance mp = tl.get();
		mp.printPerformance();
	}
}

//AOP橫切模組
public class PerfermanceHandler implements InvocationHandler{
	private Object target;
	
	public PerfermanceHandler(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		PerformanceMonitor.begin(target.getClass().getName()+"."+method.getName());
		Object object = method.invoke(target, args);
		PerformanceMonitor.end();
		return object;
	}

}
//測試
public class TestForumService {
	public static void main(String[] args) {
		ForumService target = new ForumServiceImpl();
		//將目標業務類與橫切程式碼編織到一起
		PerfermanceHandler handler = new PerfermanceHandler(target);
		//建立代理例項
		ForumService proxy = (ForumService) Proxy.newProxyInstance(target.getClass().getClassLoader(), 
													target.getClass().getInterfaces(), handler);
		proxy.removeForum(10);
		proxy.removeTopic(1012);
		
	}
}

begin monitor

模擬刪除Forum記錄:10

end monitor

com.baobaotao.proxy.ForumServiceImpl.removeForum cost 42ms

begin monitor

模擬刪除Topic記錄:1012

end monitor

com.baobaotao.proxy.ForumServiceImpl.removeTopic cost 21ms

2.CGLib採用底層的位元組碼技術,為一個類建立子類,並在子類中採用方法攔截的技術攔截所有父類的呼叫方法,並順勢織入橫切邏輯。

package com.baobaotao.proxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

	private Enhancer enhancer = new Enhancer();
	
	public Object getProxy(Class clazz){
		enhancer.setSuperclass(clazz);//設定建立子類的類
		enhancer.setCallback(this);
		return enhancer.create();//通過位元組碼技術動態建立子類例項
	}
	
	@Override
	public Object intercept(Object target, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		PerformanceMonitor.begin(target.getClass().getName()+"."+method.getName());
		Object object = proxy.invokeSuper(target, args);
		PerformanceMonitor.end();
		return object;
	}
}
package com.baobaotao.proxy;

import java.lang.reflect.Proxy;
//測試
public class TestForumService {
	public static void main(String[] args) {	
		CglibProxy cglibProxy = new CglibProxy();
		ForumServiceImpl service = (ForumServiceImpl) cglibProxy.getProxy(ForumServiceImpl.class);
		service.removeForum(10);
		service.removeTopic(1012);
	}
}

begin monitor

模擬刪除Forum記錄:10

end monitor

com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$626e31f5(子類).removeForum cost 67ms

begin monitor

模擬刪除Topic記錄:1012

end monitor

com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$626e31f5.removeTopic cost 20ms

Spring增強類

Spring支援5種增強型別:

1)前置增強:org.springframework.aop.BeforeAdvice代表前置增強,spring只支援方法級的增強,目前可用MethodBeforeAdvice。

public interface Waiter {
	public void greetTo(String name);
	public void serveTo(String name);
}
public class NaiveWaiter implements Waiter {

	@Override
	public void greetTo(String name) {
		System.out.println("greetTo "+ name +"...");
	}

	@Override
	public void serveTo(String name) {
		System.out.println("serveTo "+ name +"...");		
	}
}
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class GreeteBeforeAdvice implements MethodBeforeAdvice{

	@Override
	public void before(Method arg0, Object[] arg1, Object arg2)
			throws Throwable {
		String client = (String) arg1[0];
		System.out.println("How are you!"+client+".");
	}
}
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class TestBeforeAdvice {

	public static void main(String[] args) {
		Waiter target = new NaiveWaiter();
		BeforeAdvice advice = new GreeteBeforeAdvice();
		//Spring提供的代理工廠
		ProxyFactory pf = new ProxyFactory();//使用Cglib2AOPProx 即CGlib代理技術建立代理
//		pf.setInterfaces(target.getClass().getInterfaces());//使用JdkDynamicAopProxy
		//設定代理目標
		pf.setTarget(target);
		//新增增強處理
		pf.addAdvice(advice);
		//生成代理例項
		Waiter waiter = (Waiter) pf.getProxy();
		waiter.greetTo("Tom");
		waiter.serveTo("Lucy");
		
//		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
//		Waiter waiter1 = (Waiter) ctx.getBean("waiter");
//		waiter1.greetTo("John");		
	}
}
<bean id="target" class="com.baobaotao.advice.NaiveWaiter" />
	<bean id="greeteAdvice" class="com.baobaotao.advice.GreeteBeforeAdvice" />
	<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="com.baobaotao.advice.Waiter" p:interceptorNames="greeteAdvice"
		p:target-ref="target" />

2)後置增強:org.springframework.aop.AfterReturningAdvice代表後置增強,在目標方法執行後實施增強。

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class GreeteAfterAdvice implements AfterReturningAdvice{
	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2,
			Object arg3) throws Throwable {
		System.out.println("Please enjoy yourself!");
	}
}
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="com.baobaotao.advice.Waiter" p:interceptorNames="greeteBefore,greeteAfter"
		p:target-ref="target" />

3)環繞增強:org.aopalliance.intercept.MethodInterceptor代表環繞增強,在目標方法執行前後實施增強。

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class GreeteInterceptor implements MethodInterceptor{

	@Override
	public Object invoke(MethodInvocation inv) throws Throwable {
		Object[] args = inv.getArguments();
		String client = (String) args[0];
		System.out.println("How are you!"+client+".");
		Object obj = inv.proceed();
		System.out.println("Please enjoy yourself!");
		return obj;
	}

}

4)異常丟擲增強:org.springframework.aop.ThrowsAdvice,在目標方法執行丟擲異常後實施增強。方法名必須為afterThrowing,如參前三個可選,最後一個是Throwable或其子類。

import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class TransactionManager implements ThrowsAdvice {
	public void afterThrowing(Method method, Object[] args, Object target,
			Exception ex) throws Throwable {
		System.out.println("-----------");
		System.out.println("method:" + method.getName());
		System.out.println("丟擲異常:" + ex.getMessage());
		System.out.println("成功回滾事務。");
	}
}

5)引介增強:org.springframework.aop.IntroductionInterceptor,表示目標類新增一些新的方法和屬性,連線點是類級別,而不是方法級別。

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;

import com.baobaotao.proxy.PerformanceMonitor;

public class ControllablePerformaceMonitor extends DelegatingIntroductionInterceptor implements Monitorable{
	private ThreadLocal<Boolean> MonitorStatusMap = new ThreadLocal<Boolean>();
	@Override
	public void setMonitorActive(boolean active) {
		MonitorStatusMap.set(active);
	}
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		Object obj = null;
		if (MonitorStatusMap.get() != null && MonitorStatusMap.get()) {
			PerformanceMonitor.begin(mi.getClass().getName() + "."
					+ mi.getMethod().getName());
			obj = super.invoke(mi);
			PerformanceMonitor.end();
		} else {
			obj = super.invoke(mi);
		}
		return obj;
	}

}
<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interfaces="com.baobaotao.introduce.Monitorable" //引入引介增強要實現的介面
		p:target-ref="forumServiceTarget"
		p:interceptorNames="pmonitor" 
		p:proxyTargetClass="true" />//只能通過為目標型別類建立子類的方式生成增強的代理

AOP切面的配置方式

1)基於Schema的配置:在xml中描述切點、增強型別,切面類為pojo

2)基於AspectJ的配置:切點、增強型別使用註解進行描述

相關推薦

if(true){ I love it }】留下積累的每一份知識

專欄達人 授予成功建立個人部落格專欄

if(true){ I love it }

轉載地址:https://my.oschina.net/elain/blog/382494 一、什麼是 AOP AOP(Aspect-OrientedProgramming,面向切面程式設計),可以說是OOP(Object-Oriented Programing,面向物件

[HDU1754]I Hate It線段樹裸題

getc har namespace getch div names tchar c++ 定義 http://acm.hdu.edu.cn/showproblem.php?pid=1754 解題關鍵:剛開始死活超時,最後發現竟然是ch,和t1、t2每次循環都定義的鍋,以後

hdu1754 I Hate It

chm 學校 pda ott main update ron hdu1754 其中 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。這讓很多學生很反感。不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢問。當然,

hdu 1754 I Hate It 線段樹 點改動

dsm time opc stdin sca fun iostream nim mini // hdu 1754 I Hate It 線段樹 點改動 // // 不多說,裸的點改動 // // 繼續練 #include <algorithm> #includ

[HDOJ1754]I Hate It(分塊)

using cnblogs names eof sca 鏈接 include ons code 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 題意:老題了,現場賽總是有很多題,雖然想不到正解,但是服務器都比較勁,用分

HDU 1754 I Hate it (線段樹最大值模板)

mod algorithm font 求和 span space eof reat data- 思路:與我發表的上一遍求和的思想一樣 僅僅是如今變成求最大值而已 AC代碼: #include<iostream> #include<cstdio>

HDU 1754 I Hate It<區間最值 單點修改>

des div 分數 流行 esc ble lin problems php I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota

hdu1754 I hate it (線段樹)

文件 build dash ota pan pos 最大 eps track I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot

POJ 1678 I Love this Game

first 先行者 logs 最大差值 sin return algo pre sstream 題目鏈接:http://poj.org/problem?id=1678 動態博弈。用dp[i]來表示如果先行者首先選擇第i個數字的話能取得的最大差值。由於每次選擇的數字一定比上一

HDU - 1754 I Hate It (線段樹區間求最值)

clas lan () esp tdi typedef show scanf ons 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 題意:線段樹的單點更新和區間求最值 模板題,,,???,, 1 #in

【線段樹】I Hate It

程序 printf 處理 其中 bmi ott 學生 ref 兩個 I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub

HDU-1754 I Hate It(線段樹、點變化+段查詢---模板)

區間 printf desc d+ ++ pda ava des mission I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot

HDU1754 I HATE IT【線段樹】

hdu1754 一個 比較 har space 文件 include 分數 程序 題面: Problem Description 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是

J - I Hate It HDU - 1754

out 成績 tree 同學 treenode 線段樹 stdio.h temp 測試的 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢

HDU - 1754 I Hate It

std names 模擬 hint blog style while cout pac 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的

HDU 1754: I Hate It

define date author -s for i hate it using lin http ///@author Sycamore///@date 9/17/2017///@link http://acm.hdu.edu.cn/showproblem.php?pi

I hate it [HDU 1754]

一行 pretty tchar processor turn 復雜 一次 pda ace 題目描述 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序

B - I Hate It

har pan tex fff iostream fin space 16px nta B - I Hate It HDU - 1754 思路:線段樹板子。 #include<cstdio> #include<cstri

洛谷 P1531 I Hate It

需要 namespace 字符 ref str 現在 .org build blog P1531 I Hate It 題目背景 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。這讓很多學生很反感。 題目描述 不管你喜不喜歡,現在需要你做的是